lexxy 0.9.1.beta → 0.9.3.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 +564 -119
- 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
|
@@ -4952,9 +4952,22 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
4952
4952
|
}
|
|
4953
4953
|
|
|
4954
4954
|
disconnectedCallback() {
|
|
4955
|
+
this.dispose();
|
|
4956
|
+
}
|
|
4957
|
+
|
|
4958
|
+
dispose() {
|
|
4955
4959
|
this.#uninstallResizeObserver();
|
|
4960
|
+
this.#unbindButtons();
|
|
4956
4961
|
this.#unbindHotkeys();
|
|
4957
4962
|
this.#unbindFocusListeners();
|
|
4963
|
+
this.unregisterSelectionListener?.();
|
|
4964
|
+
this.unregisterHistoryListener?.();
|
|
4965
|
+
|
|
4966
|
+
this.editorElement = null;
|
|
4967
|
+
this.editor = null;
|
|
4968
|
+
this.selection = null;
|
|
4969
|
+
|
|
4970
|
+
this.#createEditorPromise();
|
|
4958
4971
|
}
|
|
4959
4972
|
|
|
4960
4973
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -4998,10 +5011,12 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
4998
5011
|
this.connectedCallback();
|
|
4999
5012
|
}
|
|
5000
5013
|
|
|
5001
|
-
#createEditorPromise() {
|
|
5014
|
+
async #createEditorPromise() {
|
|
5002
5015
|
this.editorPromise = new Promise((resolve) => {
|
|
5003
5016
|
this.resolveEditorPromise = resolve;
|
|
5004
5017
|
});
|
|
5018
|
+
|
|
5019
|
+
this.editorElement = await this.editorPromise;
|
|
5005
5020
|
}
|
|
5006
5021
|
|
|
5007
5022
|
#installResizeObserver() {
|
|
@@ -5017,10 +5032,14 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
5017
5032
|
}
|
|
5018
5033
|
|
|
5019
5034
|
#bindButtons() {
|
|
5020
|
-
this.addEventListener("click", this.#handleButtonClicked
|
|
5035
|
+
this.addEventListener("click", this.#handleButtonClicked);
|
|
5036
|
+
}
|
|
5037
|
+
|
|
5038
|
+
#unbindButtons() {
|
|
5039
|
+
this.removeEventListener("click", this.#handleButtonClicked);
|
|
5021
5040
|
}
|
|
5022
5041
|
|
|
5023
|
-
#handleButtonClicked(event) {
|
|
5042
|
+
#handleButtonClicked = (event) => {
|
|
5024
5043
|
this.#handleTargetClicked(event, "[data-command]", this.#dispatchButtonCommand.bind(this));
|
|
5025
5044
|
}
|
|
5026
5045
|
|
|
@@ -5080,8 +5099,8 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
5080
5099
|
}
|
|
5081
5100
|
|
|
5082
5101
|
#unbindFocusListeners() {
|
|
5083
|
-
this.editorElement
|
|
5084
|
-
this.editorElement
|
|
5102
|
+
this.editorElement?.removeEventListener("lexxy:focus", this.#handleEditorFocus);
|
|
5103
|
+
this.editorElement?.removeEventListener("lexxy:blur", this.#handleEditorBlur);
|
|
5085
5104
|
this.removeEventListener("keydown", this.#handleKeydown);
|
|
5086
5105
|
}
|
|
5087
5106
|
|
|
@@ -5105,7 +5124,7 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
5105
5124
|
}
|
|
5106
5125
|
|
|
5107
5126
|
#monitorSelectionChanges() {
|
|
5108
|
-
this.editor.registerUpdateListener(() => {
|
|
5127
|
+
this.unregisterSelectionListener = this.editor.registerUpdateListener(() => {
|
|
5109
5128
|
this.editor.getEditorState().read(() => {
|
|
5110
5129
|
this.#updateButtonStates();
|
|
5111
5130
|
this.#closeDropdowns();
|
|
@@ -5114,7 +5133,7 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
5114
5133
|
}
|
|
5115
5134
|
|
|
5116
5135
|
#monitorHistoryChanges() {
|
|
5117
|
-
this.editor.registerUpdateListener(() => {
|
|
5136
|
+
this.unregisterHistoryListener = this.editor.registerUpdateListener(() => {
|
|
5118
5137
|
this.#updateUndoRedoButtonStates();
|
|
5119
5138
|
});
|
|
5120
5139
|
}
|
|
@@ -7669,6 +7688,24 @@ function isSelectionHighlighted(selection) {
|
|
|
7669
7688
|
}
|
|
7670
7689
|
}
|
|
7671
7690
|
|
|
7691
|
+
function getHighlightStyles(selection) {
|
|
7692
|
+
if (!wr(selection)) return null
|
|
7693
|
+
|
|
7694
|
+
let styles = b$3(selection.style);
|
|
7695
|
+
if (!styles.color && !styles["background-color"]) {
|
|
7696
|
+
const anchorNode = selection.anchor.getNode();
|
|
7697
|
+
if (yr(anchorNode)) {
|
|
7698
|
+
styles = b$3(anchorNode.getStyle());
|
|
7699
|
+
}
|
|
7700
|
+
}
|
|
7701
|
+
|
|
7702
|
+
const color = styles.color || null;
|
|
7703
|
+
const backgroundColor = styles["background-color"] || null;
|
|
7704
|
+
if (!color && !backgroundColor) return null
|
|
7705
|
+
|
|
7706
|
+
return { color, backgroundColor }
|
|
7707
|
+
}
|
|
7708
|
+
|
|
7672
7709
|
function hasHighlightStyles(cssOrStyles) {
|
|
7673
7710
|
const styles = typeof cssOrStyles === "string" ? b$3(cssOrStyles) : cssOrStyles;
|
|
7674
7711
|
return !!(styles.color || styles["background-color"])
|
|
@@ -8231,6 +8268,7 @@ const COMMANDS = [
|
|
|
8231
8268
|
"insertOrderedList",
|
|
8232
8269
|
"insertQuoteBlock",
|
|
8233
8270
|
"insertCodeBlock",
|
|
8271
|
+
"setCodeLanguage",
|
|
8234
8272
|
"insertHorizontalDivider",
|
|
8235
8273
|
"uploadImage",
|
|
8236
8274
|
"uploadFile",
|
|
@@ -8243,9 +8281,10 @@ const COMMANDS = [
|
|
|
8243
8281
|
|
|
8244
8282
|
class CommandDispatcher {
|
|
8245
8283
|
#selectionBeforeDrag = null
|
|
8284
|
+
#unregister = []
|
|
8246
8285
|
|
|
8247
8286
|
static configureFor(editorElement) {
|
|
8248
|
-
new CommandDispatcher(editorElement)
|
|
8287
|
+
return new CommandDispatcher(editorElement)
|
|
8249
8288
|
}
|
|
8250
8289
|
|
|
8251
8290
|
constructor(editorElement) {
|
|
@@ -8305,7 +8344,14 @@ class CommandDispatcher {
|
|
|
8305
8344
|
}
|
|
8306
8345
|
|
|
8307
8346
|
dispatchUnlink() {
|
|
8308
|
-
this
|
|
8347
|
+
this.editor.update(() => {
|
|
8348
|
+
// Let adapters signal whether unlink should target a frozen link key.
|
|
8349
|
+
if (this.editorElement.adapter.unlinkFrozenNode?.()) {
|
|
8350
|
+
return
|
|
8351
|
+
}
|
|
8352
|
+
|
|
8353
|
+
Z$1(null);
|
|
8354
|
+
});
|
|
8309
8355
|
}
|
|
8310
8356
|
|
|
8311
8357
|
dispatchInsertUnorderedList() {
|
|
@@ -8396,6 +8442,17 @@ class CommandDispatcher {
|
|
|
8396
8442
|
}
|
|
8397
8443
|
}
|
|
8398
8444
|
|
|
8445
|
+
dispatchSetCodeLanguage(language) {
|
|
8446
|
+
this.editor.update(() => {
|
|
8447
|
+
if (!this.selection.isInsideCodeBlock) return
|
|
8448
|
+
|
|
8449
|
+
const codeNode = this.selection.nearestNodeOfType(U$1);
|
|
8450
|
+
if (!codeNode) return
|
|
8451
|
+
|
|
8452
|
+
codeNode.setLanguage(language);
|
|
8453
|
+
});
|
|
8454
|
+
}
|
|
8455
|
+
|
|
8399
8456
|
dispatchInsertHorizontalDivider() {
|
|
8400
8457
|
this.contents.insertAtCursorEnsuringLineBelow(new HorizontalDividerNode());
|
|
8401
8458
|
this.editor.focus();
|
|
@@ -8457,6 +8514,13 @@ class CommandDispatcher {
|
|
|
8457
8514
|
this.editor.dispatchCommand(Ce$1, undefined);
|
|
8458
8515
|
}
|
|
8459
8516
|
|
|
8517
|
+
dispose() {
|
|
8518
|
+
while (this.#unregister.length) {
|
|
8519
|
+
const unregister = this.#unregister.pop();
|
|
8520
|
+
unregister();
|
|
8521
|
+
}
|
|
8522
|
+
}
|
|
8523
|
+
|
|
8460
8524
|
#registerCommands() {
|
|
8461
8525
|
for (const command of COMMANDS) {
|
|
8462
8526
|
const methodName = `dispatch${capitalize(command)}`;
|
|
@@ -8467,12 +8531,12 @@ class CommandDispatcher {
|
|
|
8467
8531
|
}
|
|
8468
8532
|
|
|
8469
8533
|
#registerCommandHandler(command, priority, handler) {
|
|
8470
|
-
this.editor.registerCommand(command, handler, priority);
|
|
8534
|
+
this.#unregister.push(this.editor.registerCommand(command, handler, priority));
|
|
8471
8535
|
}
|
|
8472
8536
|
|
|
8473
8537
|
#registerKeyboardCommands() {
|
|
8474
|
-
this
|
|
8475
|
-
this
|
|
8538
|
+
this.#registerCommandHandler(ve$1, Gi, this.#handleArrowRightKey.bind(this));
|
|
8539
|
+
this.#registerCommandHandler(De$2, Gi, this.#handleTabKey.bind(this));
|
|
8476
8540
|
}
|
|
8477
8541
|
|
|
8478
8542
|
#handleArrowRightKey(event) {
|
|
@@ -8587,16 +8651,6 @@ class CommandDispatcher {
|
|
|
8587
8651
|
return wr(selection) && selection.isCollapsed()
|
|
8588
8652
|
}
|
|
8589
8653
|
|
|
8590
|
-
// Not using TOGGLE_LINK_COMMAND because it's not handled unless you use React/LinkPlugin
|
|
8591
|
-
#toggleLink(url) {
|
|
8592
|
-
this.editor.update(() => {
|
|
8593
|
-
if (url === null) {
|
|
8594
|
-
Z$1(null);
|
|
8595
|
-
} else {
|
|
8596
|
-
Z$1(url);
|
|
8597
|
-
}
|
|
8598
|
-
});
|
|
8599
|
-
}
|
|
8600
8654
|
}
|
|
8601
8655
|
|
|
8602
8656
|
function capitalize(str) {
|
|
@@ -8823,8 +8877,8 @@ class ActionTextAttachmentNode extends Fi {
|
|
|
8823
8877
|
return null
|
|
8824
8878
|
}
|
|
8825
8879
|
|
|
8826
|
-
createAttachmentFigure() {
|
|
8827
|
-
const figure = createAttachmentFigure(this.contentType,
|
|
8880
|
+
createAttachmentFigure(previewable = this.isPreviewableAttachment) {
|
|
8881
|
+
const figure = createAttachmentFigure(this.contentType, previewable, this.fileName);
|
|
8828
8882
|
figure.draggable = true;
|
|
8829
8883
|
figure.dataset.lexicalNodeKey = this.__key;
|
|
8830
8884
|
|
|
@@ -8958,6 +9012,8 @@ function $isActionTextAttachmentNode(node) {
|
|
|
8958
9012
|
}
|
|
8959
9013
|
|
|
8960
9014
|
class Selection {
|
|
9015
|
+
#unregister = []
|
|
9016
|
+
|
|
8961
9017
|
constructor(editorElement) {
|
|
8962
9018
|
this.editorElement = editorElement;
|
|
8963
9019
|
this.editorContentElement = editorElement.editorContentElement;
|
|
@@ -9214,6 +9270,18 @@ class Selection {
|
|
|
9214
9270
|
return this.#findPreviousSiblingUp(anchorNode)
|
|
9215
9271
|
}
|
|
9216
9272
|
|
|
9273
|
+
dispose() {
|
|
9274
|
+
this.editorElement = null;
|
|
9275
|
+
this.editorContentElement = null;
|
|
9276
|
+
this.editor = null;
|
|
9277
|
+
this.previouslySelectedKeys = null;
|
|
9278
|
+
|
|
9279
|
+
while (this.#unregister.length) {
|
|
9280
|
+
const unregister = this.#unregister.pop();
|
|
9281
|
+
unregister();
|
|
9282
|
+
}
|
|
9283
|
+
}
|
|
9284
|
+
|
|
9217
9285
|
// When all inline code text is deleted, Lexical's selection retains the stale
|
|
9218
9286
|
// code format flag. Verify the flag is backed by actual code-formatted content:
|
|
9219
9287
|
// a code block ancestor or a text node that carries the code format.
|
|
@@ -9229,7 +9297,7 @@ class Selection {
|
|
|
9229
9297
|
// detects that stale state and clears it so newly typed text won't be
|
|
9230
9298
|
// code-formatted.
|
|
9231
9299
|
#clearStaleInlineCodeFormat() {
|
|
9232
|
-
this.editor.registerUpdateListener(({ editorState, tags }) => {
|
|
9300
|
+
this.#unregister.push(this.editor.registerUpdateListener(({ editorState, tags }) => {
|
|
9233
9301
|
if (tags.has("history-merge") || tags.has("skip-dom-selection")) return
|
|
9234
9302
|
|
|
9235
9303
|
let isStale = false;
|
|
@@ -9258,7 +9326,7 @@ class Selection {
|
|
|
9258
9326
|
});
|
|
9259
9327
|
}, 0);
|
|
9260
9328
|
}
|
|
9261
|
-
});
|
|
9329
|
+
}));
|
|
9262
9330
|
}
|
|
9263
9331
|
|
|
9264
9332
|
get #currentlySelectedKeys() {
|
|
@@ -9277,29 +9345,32 @@ class Selection {
|
|
|
9277
9345
|
}
|
|
9278
9346
|
|
|
9279
9347
|
#processSelectionChangeCommands() {
|
|
9280
|
-
this
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
|
|
9348
|
+
this.#unregister.push(ec(
|
|
9349
|
+
this.editor.registerCommand(ke$3, this.#selectPreviousNode.bind(this), Hi),
|
|
9350
|
+
this.editor.registerCommand(ve$1, this.#selectNextNode.bind(this), Hi),
|
|
9351
|
+
this.editor.registerCommand(be$2, this.#selectPreviousTopLevelNode.bind(this), Hi),
|
|
9352
|
+
this.editor.registerCommand(we$1, this.#selectNextTopLevelNode.bind(this), Hi),
|
|
9284
9353
|
|
|
9285
|
-
|
|
9354
|
+
this.editor.registerCommand(ue$2, this.#selectDecoratorNodeBeforeDeletion.bind(this), Hi),
|
|
9286
9355
|
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9356
|
+
this.editor.registerCommand(re$2, () => {
|
|
9357
|
+
this.current = $r();
|
|
9358
|
+
}, Hi)
|
|
9359
|
+
));
|
|
9290
9360
|
}
|
|
9291
9361
|
|
|
9292
9362
|
#listenForNodeSelections() {
|
|
9293
|
-
this.editor.registerCommand(oe$4, ({ target }) => {
|
|
9363
|
+
this.#unregister.push(this.editor.registerCommand(oe$4, ({ target }) => {
|
|
9294
9364
|
if (!As(target)) return false
|
|
9295
9365
|
|
|
9296
9366
|
const targetNode = Do(target);
|
|
9297
9367
|
return Li(targetNode) && this.#selectInLexical(targetNode)
|
|
9298
|
-
}, Hi);
|
|
9368
|
+
}, Hi));
|
|
9299
9369
|
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9370
|
+
const moveNextLineHandler = () => this.#selectOrAppendNextLine();
|
|
9371
|
+
const rootElement = this.editor.getRootElement();
|
|
9372
|
+
rootElement.addEventListener("lexxy:internal:move-to-next-line", moveNextLineHandler);
|
|
9373
|
+
this.#unregister.push(() => rootElement.removeEventListener("lexxy:internal:move-to-next-line", moveNextLineHandler));
|
|
9303
9374
|
}
|
|
9304
9375
|
|
|
9305
9376
|
#containEditorFocus() {
|
|
@@ -9892,9 +9963,12 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
9892
9963
|
// node is reloaded from saved state such as from history.
|
|
9893
9964
|
this.#startUploadIfNeeded();
|
|
9894
9965
|
|
|
9895
|
-
|
|
9966
|
+
// Bridge-managed uploads (uploadUrl is null) don't have file data to show
|
|
9967
|
+
// an image preview, so always show the file icon during upload.
|
|
9968
|
+
const canPreviewFile = this.isPreviewableAttachment && this.uploadUrl != null;
|
|
9969
|
+
const figure = this.createAttachmentFigure(canPreviewFile);
|
|
9896
9970
|
|
|
9897
|
-
if (
|
|
9971
|
+
if (canPreviewFile) {
|
|
9898
9972
|
const img = figure.appendChild(this.#createDOMForImage());
|
|
9899
9973
|
|
|
9900
9974
|
// load file locally to set dimensions and prevent vertical shifting
|
|
@@ -9994,6 +10068,7 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
9994
10068
|
|
|
9995
10069
|
async #startUploadIfNeeded() {
|
|
9996
10070
|
if (this.#uploadStarted) return
|
|
10071
|
+
if (!this.uploadUrl) return // Bridge-managed upload — skip DirectUpload
|
|
9997
10072
|
|
|
9998
10073
|
this.#setUploadStarted();
|
|
9999
10074
|
|
|
@@ -10010,7 +10085,9 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
10010
10085
|
this.#handleUploadError(error);
|
|
10011
10086
|
} else {
|
|
10012
10087
|
this.#dispatchEvent("lexxy:upload-end", { file: this.file, error: null });
|
|
10013
|
-
this
|
|
10088
|
+
this.editor.update(() => {
|
|
10089
|
+
this.showUploadedAttachment(blob);
|
|
10090
|
+
}, { tag: this.#backgroundUpdateTags });
|
|
10014
10091
|
}
|
|
10015
10092
|
});
|
|
10016
10093
|
}
|
|
@@ -10054,17 +10131,15 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
|
|
|
10054
10131
|
}, { tag: this.#backgroundUpdateTags });
|
|
10055
10132
|
}
|
|
10056
10133
|
|
|
10057
|
-
|
|
10058
|
-
const
|
|
10134
|
+
showUploadedAttachment(blob) {
|
|
10135
|
+
const replacementNode = this.#toActionTextAttachmentNodeWith(blob);
|
|
10136
|
+
this.replace(replacementNode);
|
|
10059
10137
|
|
|
10060
|
-
|
|
10061
|
-
|
|
10062
|
-
|
|
10138
|
+
if (xs(replacementNode.getParent())) {
|
|
10139
|
+
replacementNode.selectNext();
|
|
10140
|
+
}
|
|
10063
10141
|
|
|
10064
|
-
|
|
10065
|
-
replacementNode.selectNext();
|
|
10066
|
-
}
|
|
10067
|
-
}, { tag: this.#backgroundUpdateTags });
|
|
10142
|
+
return replacementNode.getKey()
|
|
10068
10143
|
}
|
|
10069
10144
|
|
|
10070
10145
|
// Upload lifecycle methods (progress, completion, errors) run asynchronously and may
|
|
@@ -10434,7 +10509,11 @@ class Contents {
|
|
|
10434
10509
|
constructor(editorElement) {
|
|
10435
10510
|
this.editorElement = editorElement;
|
|
10436
10511
|
this.editor = editorElement.editor;
|
|
10512
|
+
}
|
|
10437
10513
|
|
|
10514
|
+
dispose() {
|
|
10515
|
+
this.editorElement = null;
|
|
10516
|
+
this.editor = null;
|
|
10438
10517
|
}
|
|
10439
10518
|
|
|
10440
10519
|
insertHtml(html, { tag } = {}) {
|
|
@@ -10662,6 +10741,53 @@ class Contents {
|
|
|
10662
10741
|
});
|
|
10663
10742
|
}
|
|
10664
10743
|
|
|
10744
|
+
insertPendingAttachment(file) {
|
|
10745
|
+
if (!this.editorElement.supportsAttachments) return null
|
|
10746
|
+
|
|
10747
|
+
let nodeKey = null;
|
|
10748
|
+
this.editor.update(() => {
|
|
10749
|
+
const uploadNode = new ActionTextAttachmentUploadNode({
|
|
10750
|
+
file,
|
|
10751
|
+
uploadUrl: null,
|
|
10752
|
+
blobUrlTemplate: this.editorElement.blobUrlTemplate,
|
|
10753
|
+
editor: this.editor
|
|
10754
|
+
});
|
|
10755
|
+
this.insertAtCursor(uploadNode);
|
|
10756
|
+
nodeKey = uploadNode.getKey();
|
|
10757
|
+
}, { tag: Wn });
|
|
10758
|
+
|
|
10759
|
+
if (!nodeKey) return null
|
|
10760
|
+
|
|
10761
|
+
const editor = this.editor;
|
|
10762
|
+
return {
|
|
10763
|
+
setAttributes(blob) {
|
|
10764
|
+
editor.update(() => {
|
|
10765
|
+
const node = Mo(nodeKey);
|
|
10766
|
+
if (!(node instanceof ActionTextAttachmentUploadNode)) return
|
|
10767
|
+
|
|
10768
|
+
const replacementNodeKey = node.showUploadedAttachment(blob);
|
|
10769
|
+
if (replacementNodeKey) {
|
|
10770
|
+
nodeKey = replacementNodeKey;
|
|
10771
|
+
}
|
|
10772
|
+
}, { tag: Wn });
|
|
10773
|
+
},
|
|
10774
|
+
setUploadProgress(progress) {
|
|
10775
|
+
editor.update(() => {
|
|
10776
|
+
const node = Mo(nodeKey);
|
|
10777
|
+
if (!(node instanceof ActionTextAttachmentUploadNode)) return
|
|
10778
|
+
|
|
10779
|
+
node.getWritable().progress = progress;
|
|
10780
|
+
}, { tag: Wn });
|
|
10781
|
+
},
|
|
10782
|
+
remove() {
|
|
10783
|
+
editor.update(() => {
|
|
10784
|
+
const node = Mo(nodeKey);
|
|
10785
|
+
if (node) node.remove();
|
|
10786
|
+
});
|
|
10787
|
+
}
|
|
10788
|
+
}
|
|
10789
|
+
}
|
|
10790
|
+
|
|
10665
10791
|
replaceNodeWithHTML(nodeKey, html, options = {}) {
|
|
10666
10792
|
this.editor.update(() => {
|
|
10667
10793
|
const node = Mo(nodeKey);
|
|
@@ -11218,6 +11344,18 @@ class Extensions {
|
|
|
11218
11344
|
}
|
|
11219
11345
|
}
|
|
11220
11346
|
|
|
11347
|
+
class BrowserAdapter {
|
|
11348
|
+
frozenLinkKey = null
|
|
11349
|
+
|
|
11350
|
+
dispatchAttributesChange(attributes, linkHref, highlight, headingTag) {}
|
|
11351
|
+
dispatchEditorInitialized(detail) {}
|
|
11352
|
+
freeze() {}
|
|
11353
|
+
thaw() {}
|
|
11354
|
+
unlinkFrozenNode() {
|
|
11355
|
+
return false
|
|
11356
|
+
}
|
|
11357
|
+
}
|
|
11358
|
+
|
|
11221
11359
|
// Custom TextNode exportDOM that avoids redundant bold/italic wrapping.
|
|
11222
11360
|
//
|
|
11223
11361
|
// Lexical's built-in TextNode.exportDOM() calls createDOM() which produces semantic tags
|
|
@@ -11537,11 +11675,12 @@ class TablesExtension extends LexxyExtension {
|
|
|
11537
11675
|
ze$1
|
|
11538
11676
|
],
|
|
11539
11677
|
register(editor) {
|
|
11678
|
+
Cn(editor);
|
|
11679
|
+
|
|
11540
11680
|
return ec(
|
|
11541
11681
|
// Register Lexical table plugins
|
|
11542
11682
|
Kn(editor),
|
|
11543
11683
|
An(editor, true),
|
|
11544
|
-
Cn(editor),
|
|
11545
11684
|
|
|
11546
11685
|
// Bug fix: Prevent hardcoded background color (Lexical #8089)
|
|
11547
11686
|
editor.registerNodeTransform(Ke$1, (node) => {
|
|
@@ -12268,6 +12407,8 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12268
12407
|
|
|
12269
12408
|
#initialValue = ""
|
|
12270
12409
|
#validationTextArea = document.createElement("textarea")
|
|
12410
|
+
#editorInitializedRafId = null
|
|
12411
|
+
#disposables = []
|
|
12271
12412
|
|
|
12272
12413
|
constructor() {
|
|
12273
12414
|
super();
|
|
@@ -12276,20 +12417,28 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12276
12417
|
}
|
|
12277
12418
|
|
|
12278
12419
|
connectedCallback() {
|
|
12279
|
-
this.id
|
|
12420
|
+
this.id ||= generateDomId("lexxy-editor");
|
|
12280
12421
|
this.config = new EditorConfiguration(this);
|
|
12281
12422
|
this.extensions = new Extensions(this);
|
|
12282
12423
|
|
|
12283
12424
|
this.editor = this.#createEditor();
|
|
12425
|
+
this.#disposables.push(this.editor);
|
|
12284
12426
|
|
|
12285
12427
|
this.contents = new Contents(this);
|
|
12428
|
+
this.#disposables.push(this.contents);
|
|
12429
|
+
|
|
12286
12430
|
this.selection = new Selection(this);
|
|
12431
|
+
this.#disposables.push(this.selection);
|
|
12432
|
+
|
|
12287
12433
|
this.clipboard = new Clipboard(this);
|
|
12434
|
+
this.adapter = new BrowserAdapter();
|
|
12435
|
+
|
|
12436
|
+
const commandDispatcher = CommandDispatcher.configureFor(this);
|
|
12437
|
+
this.#disposables.push(commandDispatcher);
|
|
12288
12438
|
|
|
12289
|
-
CommandDispatcher.configureFor(this);
|
|
12290
12439
|
this.#initialize();
|
|
12291
12440
|
|
|
12292
|
-
|
|
12441
|
+
this.#scheduleEditorInitializedDispatch();
|
|
12293
12442
|
this.toggleAttribute("connected", true);
|
|
12294
12443
|
|
|
12295
12444
|
this.#handleAutofocus();
|
|
@@ -12298,6 +12447,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12298
12447
|
}
|
|
12299
12448
|
|
|
12300
12449
|
disconnectedCallback() {
|
|
12450
|
+
this.#cancelEditorInitializedDispatch();
|
|
12301
12451
|
this.valueBeforeDisconnect = this.value;
|
|
12302
12452
|
this.#reset(); // Prevent hangs with Safari when morphing
|
|
12303
12453
|
}
|
|
@@ -12339,7 +12489,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12339
12489
|
get toolbarElement() {
|
|
12340
12490
|
if (!this.#hasToolbar) return null
|
|
12341
12491
|
|
|
12342
|
-
this.toolbar
|
|
12492
|
+
this.toolbar ??= this.#findOrCreateDefaultToolbar();
|
|
12343
12493
|
return this.toolbar
|
|
12344
12494
|
}
|
|
12345
12495
|
|
|
@@ -12394,6 +12544,32 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12394
12544
|
return this.config.get("richText")
|
|
12395
12545
|
}
|
|
12396
12546
|
|
|
12547
|
+
registerAdapter(adapter) {
|
|
12548
|
+
this.adapter = adapter;
|
|
12549
|
+
|
|
12550
|
+
if (!this.editor) return
|
|
12551
|
+
|
|
12552
|
+
this.#cancelEditorInitializedDispatch();
|
|
12553
|
+
this.#dispatchEditorInitialized();
|
|
12554
|
+
this.#dispatchAttributesChange();
|
|
12555
|
+
}
|
|
12556
|
+
|
|
12557
|
+
freezeSelection() {
|
|
12558
|
+
this.adapter.freeze();
|
|
12559
|
+
}
|
|
12560
|
+
|
|
12561
|
+
thawSelection() {
|
|
12562
|
+
this.adapter.thaw();
|
|
12563
|
+
}
|
|
12564
|
+
|
|
12565
|
+
dispatchAttributesChange() {
|
|
12566
|
+
this.#dispatchAttributesChange();
|
|
12567
|
+
}
|
|
12568
|
+
|
|
12569
|
+
dispatchEditorInitialized() {
|
|
12570
|
+
this.#dispatchEditorInitialized();
|
|
12571
|
+
}
|
|
12572
|
+
|
|
12397
12573
|
// TODO: Deprecate `single-line` attribute
|
|
12398
12574
|
get isSingleLineMode() {
|
|
12399
12575
|
return this.hasAttribute("single-line")
|
|
@@ -12475,6 +12651,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12475
12651
|
|
|
12476
12652
|
#createEditor() {
|
|
12477
12653
|
this.editorContentElement ||= this.#createEditorContentElement();
|
|
12654
|
+
this.appendChild(this.editorContentElement);
|
|
12478
12655
|
|
|
12479
12656
|
const editor = Qt$2({
|
|
12480
12657
|
name: "lexxy/core",
|
|
@@ -12517,6 +12694,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12517
12694
|
const editorContentElement = createElement("div", {
|
|
12518
12695
|
classList: "lexxy-editor__content",
|
|
12519
12696
|
contenteditable: true,
|
|
12697
|
+
autocapitalize: "none",
|
|
12520
12698
|
role: "textbox",
|
|
12521
12699
|
"aria-multiline": true,
|
|
12522
12700
|
"aria-label": this.#labelText,
|
|
@@ -12524,7 +12702,6 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12524
12702
|
});
|
|
12525
12703
|
editorContentElement.id = `${this.id}-content`;
|
|
12526
12704
|
this.#ariaAttributes.forEach(attribute => editorContentElement.setAttribute(attribute.name, attribute.value));
|
|
12527
|
-
this.appendChild(editorContentElement);
|
|
12528
12705
|
|
|
12529
12706
|
if (this.getAttribute("tabindex")) {
|
|
12530
12707
|
editorContentElement.setAttribute("tabindex", this.getAttribute("tabindex"));
|
|
@@ -12579,6 +12756,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12579
12756
|
this.#internalFormValue = this.value;
|
|
12580
12757
|
this.#toggleEmptyStatus();
|
|
12581
12758
|
this.#setValidity();
|
|
12759
|
+
this.#dispatchAttributesChange();
|
|
12582
12760
|
}));
|
|
12583
12761
|
}
|
|
12584
12762
|
|
|
@@ -12600,36 +12778,48 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12600
12778
|
}
|
|
12601
12779
|
|
|
12602
12780
|
#registerComponents() {
|
|
12781
|
+
const registered = [];
|
|
12782
|
+
|
|
12603
12783
|
if (this.supportsRichText) {
|
|
12604
|
-
|
|
12605
|
-
|
|
12784
|
+
registered.push(
|
|
12785
|
+
Jt$2(this.editor),
|
|
12786
|
+
Le$2(this.editor)
|
|
12787
|
+
);
|
|
12606
12788
|
this.#registerTableComponents();
|
|
12607
12789
|
this.#registerCodeHiglightingComponents();
|
|
12608
12790
|
if (this.supportsMarkdown) {
|
|
12609
|
-
|
|
12610
|
-
|
|
12791
|
+
registered.push(
|
|
12792
|
+
Yt$1(this.editor, Jt$1),
|
|
12793
|
+
registerMarkdownLeadingTagHandler(this.editor, Jt$1)
|
|
12794
|
+
);
|
|
12611
12795
|
}
|
|
12612
12796
|
} else {
|
|
12613
|
-
z$1(this.editor);
|
|
12797
|
+
registered.push(z$1(this.editor));
|
|
12614
12798
|
}
|
|
12615
12799
|
this.historyState = H();
|
|
12616
|
-
E$1(this.editor, this.historyState, 20);
|
|
12800
|
+
registered.push(E$1(this.editor, this.historyState, 20));
|
|
12801
|
+
|
|
12802
|
+
this.#addUnregisterHandler(ec(...registered));
|
|
12617
12803
|
}
|
|
12618
12804
|
|
|
12619
12805
|
#registerTableComponents() {
|
|
12620
|
-
|
|
12621
|
-
|
|
12806
|
+
let tableTools = this.querySelector("lexxy-table-tools");
|
|
12807
|
+
tableTools ??= createElement("lexxy-table-tools");
|
|
12808
|
+
this.append(tableTools);
|
|
12809
|
+
this.#disposables.push(tableTools);
|
|
12622
12810
|
}
|
|
12623
12811
|
|
|
12624
12812
|
#registerCodeHiglightingComponents() {
|
|
12625
12813
|
zt$2(this.editor);
|
|
12626
|
-
|
|
12627
|
-
|
|
12814
|
+
let codeLanguagePicker = this.querySelector("lexxy-code-language-picker");
|
|
12815
|
+
codeLanguagePicker ??= createElement("lexxy-code-language-picker");
|
|
12816
|
+
this.append(codeLanguagePicker);
|
|
12817
|
+
this.#disposables.push(codeLanguagePicker);
|
|
12628
12818
|
}
|
|
12629
12819
|
|
|
12630
12820
|
#handleEnter() {
|
|
12631
12821
|
// We can't prevent these externally using regular keydown because Lexical handles it first.
|
|
12632
|
-
this.editor.registerCommand(
|
|
12822
|
+
this.#addUnregisterHandler(this.editor.registerCommand(
|
|
12633
12823
|
Ee$2,
|
|
12634
12824
|
(event) => {
|
|
12635
12825
|
// Prevent CTRL+ENTER
|
|
@@ -12647,16 +12837,22 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12647
12837
|
return false
|
|
12648
12838
|
},
|
|
12649
12839
|
Gi
|
|
12650
|
-
);
|
|
12840
|
+
));
|
|
12651
12841
|
}
|
|
12652
12842
|
|
|
12653
12843
|
#registerFocusEvents() {
|
|
12654
12844
|
this.addEventListener("focusin", this.#handleFocusIn);
|
|
12655
12845
|
this.addEventListener("focusout", this.#handleFocusOut);
|
|
12846
|
+
|
|
12847
|
+
this.#addUnregisterHandler(() => {
|
|
12848
|
+
this.removeEventListener("focusin", this.#handleFocusIn);
|
|
12849
|
+
this.removeEventListener("focusout", this.#handleFocusOut);
|
|
12850
|
+
});
|
|
12656
12851
|
}
|
|
12657
12852
|
|
|
12658
12853
|
#handleFocusIn(event) {
|
|
12659
12854
|
if (this.#elementInEditorOrToolbar(event.target) && !this.currentlyFocused) {
|
|
12855
|
+
this.#dispatchAttributesChange();
|
|
12660
12856
|
dispatch(this, "lexxy:focus");
|
|
12661
12857
|
this.currentlyFocused = true;
|
|
12662
12858
|
}
|
|
@@ -12695,6 +12891,10 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12695
12891
|
#attachToolbar() {
|
|
12696
12892
|
if (this.#hasToolbar) {
|
|
12697
12893
|
this.toolbarElement.setEditor(this);
|
|
12894
|
+
if (typeof this.toolbarElement.dispose === "function") {
|
|
12895
|
+
this.#disposables.push(this.toolbarElement);
|
|
12896
|
+
}
|
|
12897
|
+
|
|
12698
12898
|
this.extensions.initializeToolbars();
|
|
12699
12899
|
}
|
|
12700
12900
|
}
|
|
@@ -12704,7 +12904,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12704
12904
|
if (typeof toolbarConfig === "string") {
|
|
12705
12905
|
return document.getElementById(toolbarConfig)
|
|
12706
12906
|
} else {
|
|
12707
|
-
return this.#createDefaultToolbar()
|
|
12907
|
+
return this.querySelector("lexxy-toolbar") ?? this.#createDefaultToolbar()
|
|
12708
12908
|
}
|
|
12709
12909
|
}
|
|
12710
12910
|
|
|
@@ -12733,35 +12933,129 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
12733
12933
|
}
|
|
12734
12934
|
}
|
|
12735
12935
|
|
|
12736
|
-
#
|
|
12737
|
-
|
|
12936
|
+
#dispatchAttributesChange() {
|
|
12937
|
+
let attributes = null;
|
|
12938
|
+
let linkHref = null;
|
|
12939
|
+
let highlight = null;
|
|
12940
|
+
let headingTag = null;
|
|
12738
12941
|
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
}
|
|
12942
|
+
this.editor.getEditorState().read(() => {
|
|
12943
|
+
const selection = $r();
|
|
12944
|
+
if (!wr(selection)) return
|
|
12743
12945
|
|
|
12744
|
-
|
|
12745
|
-
|
|
12946
|
+
const format = this.selection.getFormat();
|
|
12947
|
+
if (Object.keys(format).length === 0) return
|
|
12746
12948
|
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12949
|
+
const anchorNode = selection.anchor.getNode();
|
|
12950
|
+
const linkNode = vt$4(anchorNode, E$3);
|
|
12951
|
+
|
|
12952
|
+
attributes = {
|
|
12953
|
+
bold: { active: format.isBold, enabled: true },
|
|
12954
|
+
italic: { active: format.isItalic, enabled: true },
|
|
12955
|
+
strikethrough: { active: format.isStrikethrough, enabled: true },
|
|
12956
|
+
code: { active: format.isInCode, enabled: true },
|
|
12957
|
+
highlight: { active: format.isHighlight, enabled: true },
|
|
12958
|
+
link: { active: format.isInLink, enabled: true },
|
|
12959
|
+
quote: { active: format.isInQuote, enabled: true },
|
|
12960
|
+
heading: { active: format.isInHeading, enabled: true },
|
|
12961
|
+
"unordered-list": { active: format.isInList && format.listType === "bullet", enabled: true },
|
|
12962
|
+
"ordered-list": { active: format.isInList && format.listType === "number", enabled: true },
|
|
12963
|
+
undo: { active: false, enabled: this.historyState?.undoStack.length > 0 },
|
|
12964
|
+
redo: { active: false, enabled: this.historyState?.redoStack.length > 0 }
|
|
12965
|
+
};
|
|
12751
12966
|
|
|
12752
|
-
|
|
12753
|
-
|
|
12754
|
-
|
|
12755
|
-
}
|
|
12967
|
+
linkHref = linkNode ? linkNode.getURL() : null;
|
|
12968
|
+
highlight = format.isHighlight ? getHighlightStyles(selection) : null;
|
|
12969
|
+
headingTag = format.headingTag ?? null;
|
|
12970
|
+
});
|
|
12756
12971
|
|
|
12757
|
-
if (
|
|
12758
|
-
this.
|
|
12759
|
-
this.tableHandler = null;
|
|
12972
|
+
if (attributes) {
|
|
12973
|
+
this.adapter.dispatchAttributesChange(attributes, linkHref, highlight, headingTag);
|
|
12760
12974
|
}
|
|
12975
|
+
}
|
|
12761
12976
|
|
|
12762
|
-
|
|
12977
|
+
#dispatchEditorInitialized() {
|
|
12978
|
+
if (!this.adapter) return
|
|
12979
|
+
|
|
12980
|
+
this.adapter.dispatchEditorInitialized({
|
|
12981
|
+
highlightColors: this.#resolvedHighlightColors,
|
|
12982
|
+
headingFormats: this.#supportedHeadingFormats
|
|
12983
|
+
});
|
|
12984
|
+
}
|
|
12985
|
+
|
|
12986
|
+
#scheduleEditorInitializedDispatch() {
|
|
12987
|
+
this.#cancelEditorInitializedDispatch();
|
|
12988
|
+
this.#editorInitializedRafId = requestAnimationFrame(() => {
|
|
12989
|
+
this.#editorInitializedRafId = null;
|
|
12990
|
+
if (!this.isConnected || !this.adapter) return
|
|
12991
|
+
|
|
12992
|
+
dispatch(this, "lexxy:initialize");
|
|
12993
|
+
this.#dispatchEditorInitialized();
|
|
12994
|
+
});
|
|
12995
|
+
}
|
|
12996
|
+
|
|
12997
|
+
#cancelEditorInitializedDispatch() {
|
|
12998
|
+
if (this.#editorInitializedRafId == null) return
|
|
12999
|
+
|
|
13000
|
+
cancelAnimationFrame(this.#editorInitializedRafId);
|
|
13001
|
+
this.#editorInitializedRafId = null;
|
|
13002
|
+
}
|
|
13003
|
+
|
|
13004
|
+
get #resolvedHighlightColors() {
|
|
13005
|
+
const buttons = this.config.get("highlight.buttons");
|
|
13006
|
+
if (!buttons) return null
|
|
13007
|
+
|
|
13008
|
+
const colors = this.#resolveColors("color", buttons.color || []);
|
|
13009
|
+
const backgroundColors = this.#resolveColors("background-color", buttons["background-color"] || []);
|
|
13010
|
+
return { colors, backgroundColors }
|
|
13011
|
+
}
|
|
13012
|
+
|
|
13013
|
+
get #supportedHeadingFormats() {
|
|
13014
|
+
if (!this.supportsRichText) return []
|
|
13015
|
+
|
|
13016
|
+
return [
|
|
13017
|
+
{ label: "Normal", command: "setFormatParagraph", tag: null },
|
|
13018
|
+
{ label: "Large heading", command: "setFormatHeadingLarge", tag: "h2" },
|
|
13019
|
+
{ label: "Medium heading", command: "setFormatHeadingMedium", tag: "h3" },
|
|
13020
|
+
{ label: "Small heading", command: "setFormatHeadingSmall", tag: "h4" },
|
|
13021
|
+
]
|
|
13022
|
+
}
|
|
13023
|
+
|
|
13024
|
+
#resolveColors(property, cssValues) {
|
|
13025
|
+
const resolver = document.createElement("span");
|
|
13026
|
+
resolver.style.display = "none";
|
|
13027
|
+
this.appendChild(resolver);
|
|
13028
|
+
|
|
13029
|
+
const resolved = cssValues.map(cssValue => {
|
|
13030
|
+
resolver.style.setProperty(property, cssValue);
|
|
13031
|
+
const value = window.getComputedStyle(resolver).getPropertyValue(property);
|
|
13032
|
+
resolver.style.removeProperty(property);
|
|
13033
|
+
return { name: cssValue, value }
|
|
13034
|
+
});
|
|
13035
|
+
|
|
13036
|
+
resolver.remove();
|
|
13037
|
+
return resolved
|
|
13038
|
+
}
|
|
13039
|
+
|
|
13040
|
+
#reset() {
|
|
13041
|
+
this.#cancelEditorInitializedDispatch();
|
|
13042
|
+
this.#dispose();
|
|
13043
|
+
this.editorContentElement?.remove();
|
|
13044
|
+
this.editorContentElement = null;
|
|
12763
13045
|
|
|
13046
|
+
// Prevents issues with turbo morphing receiving an empty <lexxy-editor> which wipes
|
|
13047
|
+
// out the DOM for the tools, and the old toolbar reference will cause issues
|
|
13048
|
+
this.toolbar = null;
|
|
13049
|
+
}
|
|
13050
|
+
|
|
13051
|
+
#dispose() {
|
|
13052
|
+
this.#unregisterHandlers();
|
|
13053
|
+
this.adapter = null;
|
|
12764
13054
|
document.removeEventListener("turbo:before-cache", this.#handleTurboBeforeCache);
|
|
13055
|
+
|
|
13056
|
+
while (this.#disposables.length) {
|
|
13057
|
+
this.#disposables.pop().dispose();
|
|
13058
|
+
}
|
|
12765
13059
|
}
|
|
12766
13060
|
|
|
12767
13061
|
#reconnect() {
|
|
@@ -12802,14 +13096,15 @@ class ToolbarDropdown extends HTMLElement {
|
|
|
12802
13096
|
connectedCallback() {
|
|
12803
13097
|
this.container = this.closest("details");
|
|
12804
13098
|
|
|
12805
|
-
this.container.addEventListener("toggle", this.#handleToggle
|
|
12806
|
-
this.container.addEventListener("keydown", this.#handleKeyDown
|
|
13099
|
+
this.container.addEventListener("toggle", this.#handleToggle);
|
|
13100
|
+
this.container.addEventListener("keydown", this.#handleKeyDown);
|
|
12807
13101
|
|
|
12808
13102
|
this.#onToolbarEditor(this.initialize.bind(this));
|
|
12809
13103
|
}
|
|
12810
13104
|
|
|
12811
13105
|
disconnectedCallback() {
|
|
12812
|
-
this.container
|
|
13106
|
+
this.container?.removeEventListener("toggle", this.#handleToggle);
|
|
13107
|
+
this.container?.removeEventListener("keydown", this.#handleKeyDown);
|
|
12813
13108
|
}
|
|
12814
13109
|
|
|
12815
13110
|
get toolbar() {
|
|
@@ -12834,11 +13129,11 @@ class ToolbarDropdown extends HTMLElement {
|
|
|
12834
13129
|
}
|
|
12835
13130
|
|
|
12836
13131
|
async #onToolbarEditor(callback) {
|
|
12837
|
-
await this.toolbar.
|
|
13132
|
+
await this.toolbar.editorElement;
|
|
12838
13133
|
callback();
|
|
12839
13134
|
}
|
|
12840
13135
|
|
|
12841
|
-
#handleToggle() {
|
|
13136
|
+
#handleToggle = () => {
|
|
12842
13137
|
if (this.container.open) {
|
|
12843
13138
|
this.#handleOpen();
|
|
12844
13139
|
}
|
|
@@ -12849,7 +13144,7 @@ class ToolbarDropdown extends HTMLElement {
|
|
|
12849
13144
|
this.#resetTabIndexValues();
|
|
12850
13145
|
}
|
|
12851
13146
|
|
|
12852
|
-
#handleKeyDown(event) {
|
|
13147
|
+
#handleKeyDown = (event) => {
|
|
12853
13148
|
if (event.key === "Escape") {
|
|
12854
13149
|
event.stopPropagation();
|
|
12855
13150
|
this.close();
|
|
@@ -12877,27 +13172,30 @@ class LinkDropdown extends ToolbarDropdown {
|
|
|
12877
13172
|
super.connectedCallback();
|
|
12878
13173
|
this.input = this.querySelector("input");
|
|
12879
13174
|
|
|
12880
|
-
this.#
|
|
13175
|
+
this.container.addEventListener("toggle", this.#handleToggle);
|
|
13176
|
+
this.addEventListener("submit", this.#handleSubmit);
|
|
13177
|
+
this.querySelector("[value='unlink']").addEventListener("click", this.#handleUnlink);
|
|
12881
13178
|
}
|
|
12882
13179
|
|
|
12883
|
-
|
|
12884
|
-
this.container
|
|
12885
|
-
this.
|
|
12886
|
-
this.querySelector("[value='unlink']")
|
|
13180
|
+
disconnectedCallback() {
|
|
13181
|
+
this.container?.removeEventListener("toggle", this.#handleToggle);
|
|
13182
|
+
this.removeEventListener("submit", this.#handleSubmit);
|
|
13183
|
+
this.querySelector("[value='unlink']")?.removeEventListener("click", this.#handleUnlink);
|
|
13184
|
+
super.disconnectedCallback();
|
|
12887
13185
|
}
|
|
12888
13186
|
|
|
12889
|
-
#handleToggle({ newState }) {
|
|
13187
|
+
#handleToggle = ({ newState }) => {
|
|
12890
13188
|
this.input.value = this.#selectedLinkUrl;
|
|
12891
13189
|
this.input.required = newState === "open";
|
|
12892
13190
|
}
|
|
12893
13191
|
|
|
12894
|
-
#handleSubmit(event) {
|
|
13192
|
+
#handleSubmit = (event) => {
|
|
12895
13193
|
const command = event.submitter?.value;
|
|
12896
13194
|
this.editor.dispatchCommand(command, this.input.value);
|
|
12897
13195
|
this.close();
|
|
12898
13196
|
}
|
|
12899
13197
|
|
|
12900
|
-
#handleUnlink() {
|
|
13198
|
+
#handleUnlink = () => {
|
|
12901
13199
|
this.editor.dispatchCommand("unlink");
|
|
12902
13200
|
this.close();
|
|
12903
13201
|
}
|
|
@@ -12932,26 +13230,35 @@ const REMOVE_HIGHLIGHT_SELECTOR = "[data-command='removeHighlight']";
|
|
|
12932
13230
|
const NO_STYLE = Symbol("no_style");
|
|
12933
13231
|
|
|
12934
13232
|
class HighlightDropdown extends ToolbarDropdown {
|
|
12935
|
-
connectedCallback() {
|
|
12936
|
-
super.connectedCallback();
|
|
12937
|
-
this.#registerToggleHandler();
|
|
12938
|
-
}
|
|
12939
|
-
|
|
12940
13233
|
initialize() {
|
|
12941
13234
|
this.#setUpButtons();
|
|
12942
13235
|
this.#registerButtonHandlers();
|
|
12943
13236
|
}
|
|
12944
13237
|
|
|
12945
|
-
|
|
12946
|
-
|
|
13238
|
+
connectedCallback() {
|
|
13239
|
+
super.connectedCallback();
|
|
13240
|
+
this.container.addEventListener("toggle", this.#handleToggle);
|
|
13241
|
+
}
|
|
13242
|
+
|
|
13243
|
+
disconnectedCallback() {
|
|
13244
|
+
this.container?.removeEventListener("toggle", this.#handleToggle);
|
|
13245
|
+
this.#removeButtonHandlers();
|
|
13246
|
+
super.disconnectedCallback();
|
|
12947
13247
|
}
|
|
12948
13248
|
|
|
12949
13249
|
#registerButtonHandlers() {
|
|
12950
|
-
this.#colorButtons.forEach(button => button.addEventListener("click", this.#handleColorButtonClick
|
|
12951
|
-
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).addEventListener("click", this.#handleRemoveHighlightClick
|
|
13250
|
+
this.#colorButtons.forEach(button => button.addEventListener("click", this.#handleColorButtonClick));
|
|
13251
|
+
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).addEventListener("click", this.#handleRemoveHighlightClick);
|
|
13252
|
+
}
|
|
13253
|
+
|
|
13254
|
+
#removeButtonHandlers() {
|
|
13255
|
+
this.#colorButtons.forEach(button => button.removeEventListener("click", this.#handleColorButtonClick));
|
|
13256
|
+
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR)?.removeEventListener("click", this.#handleRemoveHighlightClick);
|
|
12952
13257
|
}
|
|
12953
13258
|
|
|
12954
13259
|
#setUpButtons() {
|
|
13260
|
+
this.#buttonContainer.innerHTML = "";
|
|
13261
|
+
|
|
12955
13262
|
const colorGroups = this.editorElement.config.get("highlight.buttons");
|
|
12956
13263
|
|
|
12957
13264
|
this.#populateButtonGroup("color", colorGroups.color);
|
|
@@ -12977,7 +13284,7 @@ class HighlightDropdown extends ToolbarDropdown {
|
|
|
12977
13284
|
return button
|
|
12978
13285
|
}
|
|
12979
13286
|
|
|
12980
|
-
#handleToggle({ newState }) {
|
|
13287
|
+
#handleToggle = ({ newState }) => {
|
|
12981
13288
|
if (newState === "open") {
|
|
12982
13289
|
this.editor.getEditorState().read(() => {
|
|
12983
13290
|
this.#updateColorButtonStates($r());
|
|
@@ -12985,7 +13292,7 @@ class HighlightDropdown extends ToolbarDropdown {
|
|
|
12985
13292
|
}
|
|
12986
13293
|
}
|
|
12987
13294
|
|
|
12988
|
-
#handleColorButtonClick(event) {
|
|
13295
|
+
#handleColorButtonClick = (event) => {
|
|
12989
13296
|
event.preventDefault();
|
|
12990
13297
|
|
|
12991
13298
|
const button = event.target.closest(APPLY_HIGHLIGHT_SELECTOR);
|
|
@@ -12998,7 +13305,7 @@ class HighlightDropdown extends ToolbarDropdown {
|
|
|
12998
13305
|
this.close();
|
|
12999
13306
|
}
|
|
13000
13307
|
|
|
13001
|
-
#handleRemoveHighlightClick(event) {
|
|
13308
|
+
#handleRemoveHighlightClick = (event) => {
|
|
13002
13309
|
event.preventDefault();
|
|
13003
13310
|
|
|
13004
13311
|
this.editor.dispatchCommand("removeHighlight");
|
|
@@ -13649,10 +13956,13 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
13649
13956
|
}
|
|
13650
13957
|
|
|
13651
13958
|
class CodeLanguagePicker extends HTMLElement {
|
|
13959
|
+
#abortController = null
|
|
13960
|
+
|
|
13652
13961
|
connectedCallback() {
|
|
13653
13962
|
this.editorElement = this.closest("lexxy-editor");
|
|
13654
13963
|
this.editor = this.editorElement.editor;
|
|
13655
13964
|
this.classList.add("lexxy-floating-controls");
|
|
13965
|
+
this.#abortController = new AbortController();
|
|
13656
13966
|
|
|
13657
13967
|
this.#attachLanguagePicker();
|
|
13658
13968
|
this.#hide();
|
|
@@ -13660,21 +13970,37 @@ class CodeLanguagePicker extends HTMLElement {
|
|
|
13660
13970
|
}
|
|
13661
13971
|
|
|
13662
13972
|
disconnectedCallback() {
|
|
13973
|
+
this.dispose();
|
|
13974
|
+
}
|
|
13975
|
+
|
|
13976
|
+
dispose() {
|
|
13977
|
+
this.#abortController?.abort();
|
|
13978
|
+
this.#abortController = null;
|
|
13663
13979
|
this.unregisterUpdateListener?.();
|
|
13664
13980
|
this.unregisterUpdateListener = null;
|
|
13665
13981
|
}
|
|
13666
13982
|
|
|
13667
13983
|
#attachLanguagePicker() {
|
|
13668
|
-
this.languagePickerElement = this.#createLanguagePicker();
|
|
13984
|
+
this.languagePickerElement = this.#findLanguagePicker() ?? this.#createLanguagePicker();
|
|
13985
|
+
|
|
13986
|
+
const signal = this.#abortController.signal;
|
|
13669
13987
|
|
|
13670
13988
|
this.languagePickerElement.addEventListener("change", () => {
|
|
13671
13989
|
this.#updateCodeBlockLanguage(this.languagePickerElement.value);
|
|
13672
|
-
});
|
|
13990
|
+
}, { signal });
|
|
13991
|
+
|
|
13992
|
+
this.languagePickerElement.addEventListener("mousedown", (event) => {
|
|
13993
|
+
this.#dispatchOpenEvent(event);
|
|
13994
|
+
}, { signal });
|
|
13673
13995
|
|
|
13674
13996
|
this.languagePickerElement.setAttribute("nonce", getNonce());
|
|
13675
13997
|
this.appendChild(this.languagePickerElement);
|
|
13676
13998
|
}
|
|
13677
13999
|
|
|
14000
|
+
#findLanguagePicker() {
|
|
14001
|
+
return this.querySelector("select")
|
|
14002
|
+
}
|
|
14003
|
+
|
|
13678
14004
|
#createLanguagePicker() {
|
|
13679
14005
|
const selectElement = createElement("select", { className: "lexxy-code-language-picker", "aria-label": "Pick a language…", name: "lexxy-code-language" });
|
|
13680
14006
|
|
|
@@ -13707,6 +14033,21 @@ class CodeLanguagePicker extends HTMLElement {
|
|
|
13707
14033
|
return Object.fromEntries([ plainEntry, ...sortedEntries ])
|
|
13708
14034
|
}
|
|
13709
14035
|
|
|
14036
|
+
#dispatchOpenEvent(event) {
|
|
14037
|
+
const handled = !dispatch(this.editorElement, "lexxy:code-language-picker-open", {
|
|
14038
|
+
languages: this.#bridgeLanguages,
|
|
14039
|
+
currentLanguage: this.languagePickerElement.value
|
|
14040
|
+
}, true);
|
|
14041
|
+
|
|
14042
|
+
if (handled) {
|
|
14043
|
+
event.preventDefault();
|
|
14044
|
+
}
|
|
14045
|
+
}
|
|
14046
|
+
|
|
14047
|
+
get #bridgeLanguages() {
|
|
14048
|
+
return Object.entries(this.#languages).map(([ key, name ]) => ({ key, name }))
|
|
14049
|
+
}
|
|
14050
|
+
|
|
13710
14051
|
#updateCodeBlockLanguage(language) {
|
|
13711
14052
|
this.editor.update(() => {
|
|
13712
14053
|
const codeNode = this.#getCurrentCodeNode();
|
|
@@ -14245,6 +14586,10 @@ class TableTools extends HTMLElement {
|
|
|
14245
14586
|
}
|
|
14246
14587
|
|
|
14247
14588
|
disconnectedCallback() {
|
|
14589
|
+
this.dispose();
|
|
14590
|
+
}
|
|
14591
|
+
|
|
14592
|
+
dispose() {
|
|
14248
14593
|
this.#unregisterKeyboardShortcuts();
|
|
14249
14594
|
|
|
14250
14595
|
this.unregisterUpdateListener?.();
|
|
@@ -14269,6 +14614,8 @@ class TableTools extends HTMLElement {
|
|
|
14269
14614
|
}
|
|
14270
14615
|
|
|
14271
14616
|
#setUpButtons() {
|
|
14617
|
+
this.innerHTML = "";
|
|
14618
|
+
|
|
14272
14619
|
this.appendChild(this.#createRowButtonsContainer());
|
|
14273
14620
|
this.appendChild(this.#createColumnButtonsContainer());
|
|
14274
14621
|
|
|
@@ -14696,10 +15043,108 @@ function collectTextNodes(root) {
|
|
|
14696
15043
|
return nodes
|
|
14697
15044
|
}
|
|
14698
15045
|
|
|
15046
|
+
class NativeAdapter {
|
|
15047
|
+
frozenLinkKey = null
|
|
15048
|
+
|
|
15049
|
+
constructor(editorElement) {
|
|
15050
|
+
this.editorElement = editorElement;
|
|
15051
|
+
this.editorContentElement = editorElement.editorContentElement;
|
|
15052
|
+
}
|
|
15053
|
+
|
|
15054
|
+
dispatchAttributesChange(attributes, linkHref, highlight, headingTag) {
|
|
15055
|
+
dispatch(this.editorElement, "lexxy:attributes-change", {
|
|
15056
|
+
attributes,
|
|
15057
|
+
link: linkHref ? { href: linkHref } : null,
|
|
15058
|
+
highlight,
|
|
15059
|
+
headingTag
|
|
15060
|
+
});
|
|
15061
|
+
}
|
|
15062
|
+
|
|
15063
|
+
dispatchEditorInitialized(detail) {
|
|
15064
|
+
dispatch(this.editorElement, "lexxy:editor-initialized", detail);
|
|
15065
|
+
}
|
|
15066
|
+
|
|
15067
|
+
freeze() {
|
|
15068
|
+
let frozenLinkKey = null;
|
|
15069
|
+
this.editorElement.editor?.getEditorState().read(() => {
|
|
15070
|
+
const selection = $r();
|
|
15071
|
+
if (!wr(selection)) return
|
|
15072
|
+
|
|
15073
|
+
const linkNode = vt$4(selection.anchor.getNode(), E$3);
|
|
15074
|
+
if (linkNode) {
|
|
15075
|
+
frozenLinkKey = linkNode.getKey();
|
|
15076
|
+
}
|
|
15077
|
+
});
|
|
15078
|
+
|
|
15079
|
+
this.frozenLinkKey = frozenLinkKey;
|
|
15080
|
+
this.editorContentElement.contentEditable = "false";
|
|
15081
|
+
}
|
|
15082
|
+
|
|
15083
|
+
thaw() {
|
|
15084
|
+
this.editorContentElement.contentEditable = "true";
|
|
15085
|
+
}
|
|
15086
|
+
|
|
15087
|
+
unlinkFrozenNode() {
|
|
15088
|
+
const key = this.frozenLinkKey;
|
|
15089
|
+
if (!key) return false
|
|
15090
|
+
|
|
15091
|
+
const linkNode = Mo(key);
|
|
15092
|
+
if (!B$2(linkNode)) {
|
|
15093
|
+
this.frozenLinkKey = null;
|
|
15094
|
+
return false
|
|
15095
|
+
}
|
|
15096
|
+
|
|
15097
|
+
const children = linkNode.getChildren();
|
|
15098
|
+
for (const child of children) {
|
|
15099
|
+
linkNode.insertBefore(child);
|
|
15100
|
+
}
|
|
15101
|
+
linkNode.remove();
|
|
15102
|
+
|
|
15103
|
+
// Select the former link text so a follow-up createLink can re-wrap it.
|
|
15104
|
+
const firstText = this.#findFirstTextDescendant(children);
|
|
15105
|
+
const lastText = this.#findLastTextDescendant(children);
|
|
15106
|
+
if (firstText && lastText) {
|
|
15107
|
+
const selection = $r();
|
|
15108
|
+
if (wr(selection)) {
|
|
15109
|
+
selection.anchor.set(firstText.getKey(), 0, "text");
|
|
15110
|
+
selection.focus.set(lastText.getKey(), lastText.getTextContent().length, "text");
|
|
15111
|
+
}
|
|
15112
|
+
}
|
|
15113
|
+
|
|
15114
|
+
this.frozenLinkKey = null;
|
|
15115
|
+
return true
|
|
15116
|
+
}
|
|
15117
|
+
|
|
15118
|
+
#findFirstTextDescendant(nodes) {
|
|
15119
|
+
for (const node of nodes) {
|
|
15120
|
+
if (yr(node)) return node
|
|
15121
|
+
if (Pi(node)) {
|
|
15122
|
+
const nestedTextNode = this.#findFirstTextDescendant(node.getChildren());
|
|
15123
|
+
if (nestedTextNode) return nestedTextNode
|
|
15124
|
+
}
|
|
15125
|
+
}
|
|
15126
|
+
|
|
15127
|
+
return null
|
|
15128
|
+
}
|
|
15129
|
+
|
|
15130
|
+
#findLastTextDescendant(nodes) {
|
|
15131
|
+
for (let index = nodes.length - 1; index >= 0; index--) {
|
|
15132
|
+
const node = nodes[index];
|
|
15133
|
+
if (yr(node)) return node
|
|
15134
|
+
if (Pi(node)) {
|
|
15135
|
+
const nestedTextNode = this.#findLastTextDescendant(node.getChildren());
|
|
15136
|
+
if (nestedTextNode) return nestedTextNode
|
|
15137
|
+
}
|
|
15138
|
+
}
|
|
15139
|
+
|
|
15140
|
+
return null
|
|
15141
|
+
}
|
|
15142
|
+
}
|
|
15143
|
+
|
|
14699
15144
|
const configure = Lexxy.configure;
|
|
14700
15145
|
|
|
14701
15146
|
// Pushing elements definition to after the current call stack to allow global configuration to take place first
|
|
14702
15147
|
setTimeout(defineElements, 0);
|
|
14703
15148
|
|
|
14704
|
-
export { $createActionTextAttachmentNode, $createActionTextAttachmentUploadNode, $isActionTextAttachmentNode, ActionTextAttachmentNode, ActionTextAttachmentUploadNode, CustomActionTextAttachmentNode, LexxyExtension as Extension, HorizontalDividerNode, configure, highlightCode as highlightAll, highlightCode };
|
|
15149
|
+
export { $createActionTextAttachmentNode, $createActionTextAttachmentUploadNode, $isActionTextAttachmentNode, ActionTextAttachmentNode, ActionTextAttachmentUploadNode, CustomActionTextAttachmentNode, LexxyExtension as Extension, HorizontalDividerNode, NativeAdapter, configure, highlightCode as highlightAll, highlightCode };
|
|
14705
15150
|
//# sourceMappingURL=lexxy.js.map
|