@37signals/lexxy 0.1.21-beta → 0.1.23-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.
- package/README.md +1 -1
- package/dist/lexxy.esm.js +248 -188
- package/dist/stylesheets/lexxy-content.css +400 -0
- package/dist/stylesheets/lexxy-editor.css +451 -0
- package/dist/stylesheets/lexxy-variables.css +73 -0
- package/dist/stylesheets/lexxy.css +2 -0
- package/package.json +3 -2
package/dist/lexxy.esm.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import DOMPurify from 'dompurify';
|
|
2
|
-
import { getStyleObjectFromCSS, getCSSFromStyleObject, $
|
|
3
|
-
import { $isTextNode, TextNode, $
|
|
2
|
+
import { getStyleObjectFromCSS, getCSSFromStyleObject, $getSelectionStyleValueForProperty, $patchStyleText } from '@lexical/selection';
|
|
3
|
+
import { $isTextNode, TextNode, $isRangeSelection, $getSelection, DecoratorNode, $getNodeByKey, HISTORY_MERGE_TAG, FORMAT_TEXT_COMMAND, $createTextNode, UNDO_COMMAND, REDO_COMMAND, PASTE_COMMAND, COMMAND_PRIORITY_LOW, KEY_TAB_COMMAND, COMMAND_PRIORITY_NORMAL, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, $isNodeSelection, $getRoot, $isLineBreakNode, $isElementNode, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, SELECTION_CHANGE_COMMAND, $createNodeSelection, $setSelection, $createParagraphNode, KEY_ENTER_COMMAND, COMMAND_PRIORITY_HIGH, $isParagraphNode, $insertNodes, $createLineBreakNode, CLEAR_HISTORY_COMMAND, $addUpdateTag, SKIP_DOM_SELECTION_TAG, createEditor, BLUR_COMMAND, FOCUS_COMMAND, KEY_SPACE_COMMAND } from 'lexical';
|
|
4
4
|
import { $isListNode, $isListItemNode, INSERT_UNORDERED_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, $createListNode, ListNode, ListItemNode, registerList } from '@lexical/list';
|
|
5
5
|
import { $isQuoteNode, $isHeadingNode, $createQuoteNode, $createHeadingNode, QuoteNode, HeadingNode, registerRichText } from '@lexical/rich-text';
|
|
6
6
|
import { $isCodeNode, CodeNode, normalizeCodeLang, CodeHighlightNode, registerCodeHighlighting, CODE_LANGUAGE_FRIENDLY_NAME_MAP } from '@lexical/code';
|
|
7
7
|
import { $isLinkNode, $createAutoLinkNode, $toggleLink, $createLinkNode, LinkNode, AutoLinkNode } from '@lexical/link';
|
|
8
|
+
import 'prismjs/components/prism-ruby';
|
|
9
|
+
import 'prismjs/components/prism-php';
|
|
10
|
+
import 'prismjs/components/prism-go';
|
|
11
|
+
import 'prismjs/components/prism-bash';
|
|
12
|
+
import 'prismjs/components/prism-json';
|
|
13
|
+
import 'prismjs/components/prism-diff';
|
|
8
14
|
import { $generateNodesFromDOM, $generateHtmlFromNodes } from '@lexical/html';
|
|
9
15
|
import { registerMarkdownShortcuts, TRANSFORMERS } from '@lexical/markdown';
|
|
10
16
|
import { createEmptyHistoryState, registerHistory } from '@lexical/history';
|
|
11
17
|
import { DirectUpload } from '@rails/activestorage';
|
|
12
18
|
import { marked } from 'marked';
|
|
13
|
-
import 'prismjs/components/prism-ruby';
|
|
14
19
|
|
|
15
20
|
const ALLOWED_HTML_TAGS = [ "a", "action-text-attachment", "b", "blockquote", "br", "code", "em",
|
|
16
21
|
"figcaption", "figure", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "i", "img", "li", "mark", "ol", "p", "pre", "q", "s", "strong", "ul" ];
|
|
@@ -115,7 +120,24 @@ function extendConversion(nodeKlass, conversionName, callback = (output => outpu
|
|
|
115
120
|
}
|
|
116
121
|
}
|
|
117
122
|
|
|
123
|
+
function isSelectionHighlighted(selection) {
|
|
124
|
+
if (!$isRangeSelection(selection)) return false
|
|
125
|
+
|
|
126
|
+
if (selection.isCollapsed()) {
|
|
127
|
+
return hasHighlightStyles(selection.style)
|
|
128
|
+
} else {
|
|
129
|
+
return selection.hasFormat("highlight")
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function hasHighlightStyles(cssOrStyles) {
|
|
134
|
+
const styles = typeof cssOrStyles === "string" ? getStyleObjectFromCSS(cssOrStyles) : cssOrStyles;
|
|
135
|
+
return !!(styles.color || styles["background-color"])
|
|
136
|
+
}
|
|
137
|
+
|
|
118
138
|
class LexicalToolbarElement extends HTMLElement {
|
|
139
|
+
static observedAttributes = [ "connected" ]
|
|
140
|
+
|
|
119
141
|
constructor() {
|
|
120
142
|
super();
|
|
121
143
|
this.internals = this.attachInternals();
|
|
@@ -134,6 +156,13 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
134
156
|
this._resizeObserver.disconnect();
|
|
135
157
|
this._resizeObserver = null;
|
|
136
158
|
}
|
|
159
|
+
this.#unbindHotkeys();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
163
|
+
if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
|
|
164
|
+
requestAnimationFrame(() => this.#reconnect());
|
|
165
|
+
}
|
|
137
166
|
}
|
|
138
167
|
|
|
139
168
|
setEditor(editorElement) {
|
|
@@ -141,7 +170,8 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
141
170
|
this.editor = editorElement.editor;
|
|
142
171
|
this.#bindButtons();
|
|
143
172
|
this.#bindHotkeys();
|
|
144
|
-
this.#
|
|
173
|
+
this.#setTabIndexValues();
|
|
174
|
+
this.#setItemPositionValues();
|
|
145
175
|
this.#monitorSelectionChanges();
|
|
146
176
|
this.#monitorHistoryChanges();
|
|
147
177
|
this.#refreshToolbarOverflow();
|
|
@@ -149,10 +179,9 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
149
179
|
this.toggleAttribute("connected", true);
|
|
150
180
|
}
|
|
151
181
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return Array.from(this.querySelectorAll(dialogTags))
|
|
182
|
+
#reconnect() {
|
|
183
|
+
this.disconnectedCallback();
|
|
184
|
+
this.connectedCallback();
|
|
156
185
|
}
|
|
157
186
|
|
|
158
187
|
#bindButtons() {
|
|
@@ -161,7 +190,6 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
161
190
|
|
|
162
191
|
#handleButtonClicked({ target }) {
|
|
163
192
|
this.#handleTargetClicked(target, "[data-command]", this.#dispatchButtonCommand.bind(this));
|
|
164
|
-
this.#handleTargetClicked(target, "[data-dialog-target]", this.#toggleDialog.bind(this));
|
|
165
193
|
}
|
|
166
194
|
|
|
167
195
|
#handleTargetClicked(target, selector, callback) {
|
|
@@ -176,38 +204,23 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
176
204
|
this.editor.dispatchCommand(command, payload);
|
|
177
205
|
}
|
|
178
206
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const dialogTarget = button.dataset.dialogTarget;
|
|
182
|
-
const dialog = this.querySelector("lexxy-" + dialogTarget);
|
|
183
|
-
if (!dialog) return
|
|
184
|
-
|
|
185
|
-
if (dialog.open) {
|
|
186
|
-
dialog.close();
|
|
187
|
-
} else {
|
|
188
|
-
this.#closeOpenDialogs();
|
|
189
|
-
dialog.show(button);
|
|
190
|
-
}
|
|
207
|
+
#bindHotkeys() {
|
|
208
|
+
this.editorElement.addEventListener("keydown", this.#handleHotkey);
|
|
191
209
|
}
|
|
192
210
|
|
|
193
|
-
#
|
|
194
|
-
|
|
195
|
-
openDialogs.forEach(openDialog => {
|
|
196
|
-
openDialog.closest(".lexxy-dialog").close();
|
|
197
|
-
});
|
|
211
|
+
#unbindHotkeys() {
|
|
212
|
+
this.editorElement?.removeEventListener("keydown", this.#handleHotkey);
|
|
198
213
|
}
|
|
199
214
|
|
|
200
|
-
#
|
|
201
|
-
this.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
});
|
|
215
|
+
#handleHotkey = (event) => {
|
|
216
|
+
const buttons = this.querySelectorAll("[data-hotkey]");
|
|
217
|
+
buttons.forEach((button) => {
|
|
218
|
+
const hotkeys = button.dataset.hotkey.toLowerCase().split(/\s+/);
|
|
219
|
+
if (hotkeys.includes(this.#keyCombinationFor(event))) {
|
|
220
|
+
event.preventDefault();
|
|
221
|
+
event.stopPropagation();
|
|
222
|
+
button.click();
|
|
223
|
+
}
|
|
211
224
|
});
|
|
212
225
|
}
|
|
213
226
|
|
|
@@ -223,10 +236,9 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
223
236
|
return [ ...modifiers, pressedKey ].join("+")
|
|
224
237
|
}
|
|
225
238
|
|
|
226
|
-
#
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
button.setAttribute("tabindex", `${baseTabIndex + index + 1}`);
|
|
239
|
+
#setTabIndexValues() {
|
|
240
|
+
this.#buttons.forEach((button) => {
|
|
241
|
+
button.setAttribute("tabindex", 0);
|
|
230
242
|
});
|
|
231
243
|
}
|
|
232
244
|
|
|
@@ -234,7 +246,6 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
234
246
|
this.editor.registerUpdateListener(() => {
|
|
235
247
|
this.editor.getEditorState().read(() => {
|
|
236
248
|
this.#updateButtonStates();
|
|
237
|
-
this.#updateDialogStates();
|
|
238
249
|
});
|
|
239
250
|
});
|
|
240
251
|
}
|
|
@@ -267,7 +278,7 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
267
278
|
const isBold = selection.hasFormat("bold");
|
|
268
279
|
const isItalic = selection.hasFormat("italic");
|
|
269
280
|
const isStrikethrough = selection.hasFormat("strikethrough");
|
|
270
|
-
const isHighlight = selection
|
|
281
|
+
const isHighlight = isSelectionHighlighted(selection);
|
|
271
282
|
const isInLink = this.#isInLink(anchorNode);
|
|
272
283
|
const isInQuote = $isQuoteNode(topLevelElement);
|
|
273
284
|
const isInHeading = $isHeadingNode(topLevelElement);
|
|
@@ -289,10 +300,6 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
289
300
|
this.#updateUndoRedoButtonStates();
|
|
290
301
|
}
|
|
291
302
|
|
|
292
|
-
#updateDialogStates() {
|
|
293
|
-
this.#dialogs.forEach(dialog => dialog.updateStateCallback());
|
|
294
|
-
}
|
|
295
|
-
|
|
296
303
|
#isInList(node) {
|
|
297
304
|
let current = node;
|
|
298
305
|
while (current) {
|
|
@@ -341,22 +348,8 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
341
348
|
this.toggleAttribute("overflowing", isOverflowing);
|
|
342
349
|
}
|
|
343
350
|
|
|
344
|
-
get #overflow() {
|
|
345
|
-
return this.querySelector(".lexxy-editor__toolbar-overflow")
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
get #overflowMenu() {
|
|
349
|
-
return this.querySelector(".lexxy-editor__toolbar-overflow-menu")
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
#resetToolbar() {
|
|
353
|
-
while (this.#overflowMenu.children.length > 0) {
|
|
354
|
-
this.insertBefore(this.#overflowMenu.children[0], this.#overflow);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
351
|
#compactMenu() {
|
|
359
|
-
const buttons = this.#
|
|
352
|
+
const buttons = this.#buttons.reverse();
|
|
360
353
|
let movedToOverflow = false;
|
|
361
354
|
|
|
362
355
|
for (const button of buttons) {
|
|
@@ -370,12 +363,42 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
370
363
|
}
|
|
371
364
|
}
|
|
372
365
|
|
|
366
|
+
#resetToolbar() {
|
|
367
|
+
const items = Array.from(this.#overflowMenu.children);
|
|
368
|
+
items.sort((a, b) => this.#itemPosition(b) - this.#itemPosition(a));
|
|
369
|
+
|
|
370
|
+
items.forEach((item) => {
|
|
371
|
+
const nextItem = this.querySelector(`[data-position="${this.#itemPosition(item) + 1}"]`) ?? this.#overflow;
|
|
372
|
+
this.insertBefore(item, nextItem);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#itemPosition(item) {
|
|
377
|
+
return parseInt(item.dataset.position ?? "999")
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
#setItemPositionValues() {
|
|
381
|
+
this.#toolbarItems.forEach((item, index) => {
|
|
382
|
+
if (item.dataset.position === undefined) {
|
|
383
|
+
item.dataset.position = index;
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
get #overflow() {
|
|
389
|
+
return this.querySelector(".lexxy-editor__toolbar-overflow")
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
get #overflowMenu() {
|
|
393
|
+
return this.querySelector(".lexxy-editor__toolbar-overflow-menu")
|
|
394
|
+
}
|
|
395
|
+
|
|
373
396
|
get #buttons() {
|
|
374
397
|
return Array.from(this.querySelectorAll(":scope > button"))
|
|
375
398
|
}
|
|
376
399
|
|
|
377
|
-
get #
|
|
378
|
-
return Array.from(this.querySelectorAll(":scope >
|
|
400
|
+
get #toolbarItems() {
|
|
401
|
+
return Array.from(this.querySelectorAll(":scope > *:not(.lexxy-editor__toolbar-overflow)"))
|
|
379
402
|
}
|
|
380
403
|
|
|
381
404
|
static get defaultTemplate() {
|
|
@@ -394,35 +417,31 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
394
417
|
</svg>
|
|
395
418
|
</button>
|
|
396
419
|
|
|
397
|
-
<
|
|
398
|
-
<
|
|
399
|
-
<
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
<button class="lexxy-editor__toolbar-button" type="button" name="highlight" title="Color highlight" data-dialog-target="highlight-dialog">
|
|
408
|
-
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.65422 0.711575C7.1856 0.242951 6.42579 0.242951 5.95717 0.711575C5.48853 1.18021 5.48853 1.94 5.95717 2.40864L8.70864 5.16011L2.85422 11.0145C1.44834 12.4204 1.44833 14.6998 2.85422 16.1057L7.86011 21.1115C9.26599 22.5174 11.5454 22.5174 12.9513 21.1115L19.6542 14.4087C20.1228 13.94 20.1228 13.1802 19.6542 12.7115L11.8544 4.91171L11.2542 4.31158L7.65422 0.711575ZM4.55127 12.7115L10.4057 6.85716L17.1087 13.56H4.19981C4.19981 13.253 4.31696 12.9459 4.55127 12.7115ZM23.6057 20.76C23.6057 22.0856 22.5311 23.16 21.2057 23.16C19.8802 23.16 18.8057 22.0856 18.8057 20.76C18.8057 19.5408 19.8212 18.5339 20.918 17.4462C21.0135 17.3516 21.1096 17.2563 21.2057 17.16C21.3018 17.2563 21.398 17.3516 21.4935 17.4462C22.5903 18.5339 23.6057 19.5408 23.6057 20.76Z"/></svg>
|
|
409
|
-
</button>
|
|
420
|
+
<details class="lexxy-editor__toolbar-dropdown" name="lexxy-dropdown">
|
|
421
|
+
<summary class="lexxy-editor__toolbar-button" name="highlight" title="Color highlight">
|
|
422
|
+
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.65422 0.711575C7.1856 0.242951 6.42579 0.242951 5.95717 0.711575C5.48853 1.18021 5.48853 1.94 5.95717 2.40864L8.70864 5.16011L2.85422 11.0145C1.44834 12.4204 1.44833 14.6998 2.85422 16.1057L7.86011 21.1115C9.26599 22.5174 11.5454 22.5174 12.9513 21.1115L19.6542 14.4087C20.1228 13.94 20.1228 13.1802 19.6542 12.7115L11.8544 4.91171L11.2542 4.31158L7.65422 0.711575ZM4.55127 12.7115L10.4057 6.85716L17.1087 13.56H4.19981C4.19981 13.253 4.31696 12.9459 4.55127 12.7115ZM23.6057 20.76C23.6057 22.0856 22.5311 23.16 21.2057 23.16C19.8802 23.16 18.8057 22.0856 18.8057 20.76C18.8057 19.5408 19.8212 18.5339 20.918 17.4462C21.0135 17.3516 21.1096 17.2563 21.2057 17.16C21.3018 17.2563 21.398 17.3516 21.4935 17.4462C22.5903 18.5339 23.6057 19.5408 23.6057 20.76Z"/></svg>
|
|
423
|
+
</summary>
|
|
424
|
+
<lexxy-highlight-dropdown class="lexxy-editor__toolbar-dropdown-content">
|
|
425
|
+
<div data-button-group="color" data-values="var(--highlight-1); var(--highlight-2); var(--highlight-3); var(--highlight-4); var(--highlight-5); var(--highlight-6); var(--highlight-7); var(--highlight-8); var(--highlight-9)"></div>
|
|
426
|
+
<div data-button-group="background-color" data-values="var(--highlight-bg-1); var(--highlight-bg-2); var(--highlight-bg-3); var(--highlight-bg-4); var(--highlight-bg-5); var(--highlight-bg-6); var(--highlight-bg-7); var(--highlight-bg-8); var(--highlight-bg-9)"></div>
|
|
427
|
+
<button data-command="removeHighlight" class="lexxy-editor__toolbar-dropdown-reset">Remove all coloring</button>
|
|
428
|
+
</lexxy-highlight-dropdown>
|
|
429
|
+
</details>
|
|
410
430
|
|
|
411
|
-
<
|
|
412
|
-
<
|
|
431
|
+
<details class="lexxy-editor__toolbar-dropdown" name="lexxy-dropdown">
|
|
432
|
+
<summary class="lexxy-editor__toolbar-button" name="link" title="Link" data-hotkey="cmd+k ctrl+k">
|
|
433
|
+
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.111 9.546a1.5 1.5 0 012.121 0 5.5 5.5 0 010 7.778l-2.828 2.828a5.5 5.5 0 01-7.778 0 5.498 5.498 0 010-7.777l2.828-2.83a1.5 1.5 0 01.355-.262 6.52 6.52 0 00.351 3.799l-1.413 1.414a2.499 2.499 0 000 3.535 2.499 2.499 0 003.535 0l2.83-2.828a2.5 2.5 0 000-3.536 1.5 1.5 0 010-2.121z"/><path d="M12.111 3.89a5.5 5.5 0 117.778 7.777l-2.828 2.829a1.496 1.496 0 01-.355.262 6.522 6.522 0 00-.351-3.8l1.413-1.412a2.5 2.5 0 10-3.536-3.535l-2.828 2.828a2.5 2.5 0 000 3.536 1.5 1.5 0 01-2.122 2.12 5.5 5.5 0 010-7.777l2.83-2.829z"/></svg>
|
|
434
|
+
</summary>
|
|
435
|
+
<lexxy-link-dropdown class="lexxy-editor__toolbar-dropdown-content">
|
|
413
436
|
<form method="dialog">
|
|
414
|
-
<input type="url" placeholder="Enter a URL…" class="input"
|
|
415
|
-
<div class="lexxy-
|
|
437
|
+
<input type="url" placeholder="Enter a URL…" class="input">
|
|
438
|
+
<div class="lexxy-editor__toolbar-dropdown-actions">
|
|
416
439
|
<button type="submit" class="btn" value="link">Link</button>
|
|
417
440
|
<button type="button" class="btn" value="unlink">Unlink</button>
|
|
418
441
|
</div>
|
|
419
442
|
</form>
|
|
420
|
-
</
|
|
421
|
-
</
|
|
422
|
-
|
|
423
|
-
<button class="lexxy-editor__toolbar-button" type="button" name="link" title="Link" data-dialog-target="link-dialog" data-hotkey="cmd+k ctrl+k">
|
|
424
|
-
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.111 9.546a1.5 1.5 0 012.121 0 5.5 5.5 0 010 7.778l-2.828 2.828a5.5 5.5 0 01-7.778 0 5.498 5.498 0 010-7.777l2.828-2.83a1.5 1.5 0 01.355-.262 6.52 6.52 0 00.351 3.799l-1.413 1.414a2.499 2.499 0 000 3.535 2.499 2.499 0 003.535 0l2.83-2.828a2.5 2.5 0 000-3.536 1.5 1.5 0 010-2.121z"/><path d="M12.111 3.89a5.5 5.5 0 117.778 7.777l-2.828 2.829a1.496 1.496 0 01-.355.262 6.522 6.522 0 00-.351-3.8l1.413-1.412a2.5 2.5 0 10-3.536-3.535l-2.828 2.828a2.5 2.5 0 000 3.536 1.5 1.5 0 01-2.122 2.12 5.5 5.5 0 010-7.777l2.83-2.829z"/></svg>
|
|
425
|
-
</button>
|
|
443
|
+
</lexxy-link-dropdown>
|
|
444
|
+
</details>
|
|
426
445
|
|
|
427
446
|
<button class="lexxy-editor__toolbar-button" type="button" name="quote" data-command="insertQuoteBlock" title="Quote">
|
|
428
447
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.5 5C8.985 5 11 7.09 11 9.667c0 2.694-.962 5.005-2.187 6.644-.613.82-1.3 1.481-1.978 1.943-.668.454-1.375.746-2.022.746a.563.563 0 01-.52-.36.602.602 0 01.067-.57l.055-.066.009-.009.041-.048a4.25 4.25 0 00.168-.21c.143-.188.336-.47.53-.84a6.743 6.743 0 00.75-2.605C3.705 13.994 2 12.038 2 9.667 2 7.089 4.015 5 6.5 5zM17.5 5C19.985 5 22 7.09 22 9.667c0 2.694-.962 5.005-2.187 6.644-.613.82-1.3 1.481-1.978 1.943-.668.454-1.375.746-2.023.746a.563.563 0 01-.52-.36.602.602 0 01.068-.57l.055-.066.009-.009.041-.048c.039-.045.097-.115.168-.21a6.16 6.16 0 00.53-.84 6.745 6.745 0 00.75-2.605C14.705 13.994 13 12.038 13 9.667 13 7.089 15.015 5 17.5 5z"/></svg>
|
|
@@ -486,6 +505,7 @@ var theme = {
|
|
|
486
505
|
}
|
|
487
506
|
},
|
|
488
507
|
codeHighlight: {
|
|
508
|
+
addition: "code-token__selector",
|
|
489
509
|
atrule: "code-token__attr",
|
|
490
510
|
attr: "code-token__attr",
|
|
491
511
|
"attr-name": "code-token__attr",
|
|
@@ -500,24 +520,30 @@ var theme = {
|
|
|
500
520
|
color: "code-token__property",
|
|
501
521
|
comment: "code-token__comment",
|
|
502
522
|
constant: "code-token__property",
|
|
503
|
-
coord: "code-
|
|
523
|
+
coord: "code-token__comment",
|
|
504
524
|
decorator: "code-token__function",
|
|
505
|
-
deleted: "code-
|
|
525
|
+
deleted: "code-token__operator",
|
|
526
|
+
deletion: "code-token__operator",
|
|
527
|
+
directive: "code-token__attr",
|
|
528
|
+
"directive-hash": "code-token__property",
|
|
506
529
|
doctype: "code-token__comment",
|
|
507
530
|
entity: "code-token__operator",
|
|
508
531
|
function: "code-token__function",
|
|
509
532
|
hexcode: "code-token__property",
|
|
510
|
-
important: "code-
|
|
533
|
+
important: "code-token__function",
|
|
511
534
|
inserted: "code-token__selector",
|
|
512
535
|
italic: "code-token__comment",
|
|
513
536
|
keyword: "code-token__attr",
|
|
537
|
+
line: "code-token__selector",
|
|
514
538
|
namespace: "code-token__variable",
|
|
515
539
|
number: "code-token__property",
|
|
540
|
+
macro: "code-token__function",
|
|
516
541
|
operator: "code-token__operator",
|
|
517
542
|
parameter: "code-token__variable",
|
|
518
543
|
prolog: "code-token__comment",
|
|
519
544
|
property: "code-token__property",
|
|
520
545
|
punctuation: "code-token__punctuation",
|
|
546
|
+
"raw-string": "code-token__operator",
|
|
521
547
|
regex: "code-token__variable",
|
|
522
548
|
script: "code-token__function",
|
|
523
549
|
selector: "code-token__selector",
|
|
@@ -526,6 +552,7 @@ var theme = {
|
|
|
526
552
|
symbol: "code-token__property",
|
|
527
553
|
tag: "code-token__property",
|
|
528
554
|
title: "code-token__function",
|
|
555
|
+
"type-definition": "code-token__function",
|
|
529
556
|
url: "code-token__operator",
|
|
530
557
|
variable: "code-token__variable",
|
|
531
558
|
}
|
|
@@ -1108,6 +1135,7 @@ class CommandDispatcher {
|
|
|
1108
1135
|
this.highlighter = editorElement.highlighter;
|
|
1109
1136
|
|
|
1110
1137
|
this.#registerCommands();
|
|
1138
|
+
this.#registerKeyboardCommands();
|
|
1111
1139
|
this.#registerDragAndDropHandlers();
|
|
1112
1140
|
}
|
|
1113
1141
|
|
|
@@ -1272,15 +1300,8 @@ class CommandDispatcher {
|
|
|
1272
1300
|
this.editor.registerCommand(command, handler, priority);
|
|
1273
1301
|
}
|
|
1274
1302
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
this.editor.update(() => {
|
|
1278
|
-
if (url === null) {
|
|
1279
|
-
$toggleLink(null);
|
|
1280
|
-
} else {
|
|
1281
|
-
$toggleLink(url);
|
|
1282
|
-
}
|
|
1283
|
-
});
|
|
1303
|
+
#registerKeyboardCommands() {
|
|
1304
|
+
this.editor.registerCommand(KEY_TAB_COMMAND, this.#handleListIndentation.bind(this), COMMAND_PRIORITY_NORMAL);
|
|
1284
1305
|
}
|
|
1285
1306
|
|
|
1286
1307
|
#registerDragAndDropHandlers() {
|
|
@@ -1329,6 +1350,29 @@ class CommandDispatcher {
|
|
|
1329
1350
|
|
|
1330
1351
|
this.editor.focus();
|
|
1331
1352
|
}
|
|
1353
|
+
|
|
1354
|
+
#handleListIndentation(event) {
|
|
1355
|
+
if (this.selection.isInsideList) {
|
|
1356
|
+
event.preventDefault();
|
|
1357
|
+
if (event.shiftKey) {
|
|
1358
|
+
return this.editor.dispatchCommand(OUTDENT_CONTENT_COMMAND, undefined)
|
|
1359
|
+
} else {
|
|
1360
|
+
return this.editor.dispatchCommand(INDENT_CONTENT_COMMAND, undefined)
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
return false
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// Not using TOGGLE_LINK_COMMAND because it's not handled unless you use React/LinkPlugin
|
|
1367
|
+
#toggleLink(url) {
|
|
1368
|
+
this.editor.update(() => {
|
|
1369
|
+
if (url === null) {
|
|
1370
|
+
$toggleLink(null);
|
|
1371
|
+
} else {
|
|
1372
|
+
$toggleLink(url);
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1332
1376
|
}
|
|
1333
1377
|
|
|
1334
1378
|
function capitalize(str) {
|
|
@@ -3234,27 +3278,37 @@ class Clipboard {
|
|
|
3234
3278
|
class Highlighter {
|
|
3235
3279
|
constructor(editorElement) {
|
|
3236
3280
|
this.editor = editorElement.editor;
|
|
3281
|
+
|
|
3282
|
+
this.#registerHighlightTransform();
|
|
3237
3283
|
}
|
|
3238
3284
|
|
|
3239
3285
|
toggle(styles) {
|
|
3240
3286
|
this.editor.update(() => {
|
|
3241
3287
|
this.#toggleSelectionStyles(styles);
|
|
3242
|
-
$forEachSelectedTextNode(node => this.#syncHighlightWithStyle(node));
|
|
3243
3288
|
});
|
|
3244
3289
|
}
|
|
3245
3290
|
|
|
3246
3291
|
remove() {
|
|
3247
|
-
this.toggle({ "color":
|
|
3292
|
+
this.toggle({ "color": null, "background-color": null });
|
|
3293
|
+
}
|
|
3294
|
+
|
|
3295
|
+
#registerHighlightTransform() {
|
|
3296
|
+
return this.editor.registerNodeTransform(TextNode, (textNode) => {
|
|
3297
|
+
this.#syncHighlightWithStyle(textNode);
|
|
3298
|
+
})
|
|
3248
3299
|
}
|
|
3249
3300
|
|
|
3250
3301
|
#toggleSelectionStyles(styles) {
|
|
3251
3302
|
const selection = $getSelection();
|
|
3303
|
+
if (!$isRangeSelection(selection)) return
|
|
3252
3304
|
|
|
3305
|
+
const patch = {};
|
|
3253
3306
|
for (const property in styles) {
|
|
3254
3307
|
const oldValue = $getSelectionStyleValueForProperty(selection, property);
|
|
3255
|
-
|
|
3256
|
-
$patchStyleText(selection, patch);
|
|
3308
|
+
patch[property] = this.#toggleOrReplace(oldValue, styles[property]);
|
|
3257
3309
|
}
|
|
3310
|
+
|
|
3311
|
+
$patchStyleText(selection, patch);
|
|
3258
3312
|
}
|
|
3259
3313
|
|
|
3260
3314
|
#toggleOrReplace(oldValue, newValue) {
|
|
@@ -3262,15 +3316,10 @@ class Highlighter {
|
|
|
3262
3316
|
}
|
|
3263
3317
|
|
|
3264
3318
|
#syncHighlightWithStyle(node) {
|
|
3265
|
-
if (
|
|
3319
|
+
if (hasHighlightStyles(node.getStyle()) !== node.hasFormat("highlight")) {
|
|
3266
3320
|
node.toggleFormat("highlight");
|
|
3267
3321
|
}
|
|
3268
3322
|
}
|
|
3269
|
-
|
|
3270
|
-
#hasHighlightStyles(node) {
|
|
3271
|
-
const styles = getStyleObjectFromCSS(node.getStyle());
|
|
3272
|
-
return !!(styles.color || styles["background-color"])
|
|
3273
|
-
}
|
|
3274
3323
|
}
|
|
3275
3324
|
|
|
3276
3325
|
class HighlightNode extends TextNode {
|
|
@@ -3442,6 +3491,10 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
3442
3491
|
return this.getAttribute("attachments") !== "false"
|
|
3443
3492
|
}
|
|
3444
3493
|
|
|
3494
|
+
get contentTabIndex() {
|
|
3495
|
+
return parseInt(this.editorContentElement?.getAttribute("tabindex") ?? "0")
|
|
3496
|
+
}
|
|
3497
|
+
|
|
3445
3498
|
focus() {
|
|
3446
3499
|
this.editor.focus();
|
|
3447
3500
|
}
|
|
@@ -3755,39 +3808,26 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
3755
3808
|
|
|
3756
3809
|
#reconnect() {
|
|
3757
3810
|
this.disconnectedCallback();
|
|
3811
|
+
this.valueBeforeDisconnect = null;
|
|
3758
3812
|
this.connectedCallback();
|
|
3759
3813
|
}
|
|
3760
3814
|
}
|
|
3761
3815
|
|
|
3762
3816
|
customElements.define("lexxy-editor", LexicalEditorElement);
|
|
3763
3817
|
|
|
3764
|
-
class
|
|
3818
|
+
class ToolbarDropdown extends HTMLElement {
|
|
3765
3819
|
connectedCallback() {
|
|
3766
|
-
this.
|
|
3767
|
-
if ("closedBy" in this.dialog.constructor.prototype) {
|
|
3768
|
-
this.dialog.closedBy = "any";
|
|
3769
|
-
}
|
|
3770
|
-
this.#registerHandlers();
|
|
3771
|
-
}
|
|
3820
|
+
this.container = this.closest("details");
|
|
3772
3821
|
|
|
3773
|
-
|
|
3774
|
-
this.#
|
|
3775
|
-
}
|
|
3776
|
-
|
|
3777
|
-
updateStateCallback() { }
|
|
3822
|
+
this.container.addEventListener("toggle", this.#handleToggle.bind(this));
|
|
3823
|
+
this.container.addEventListener("keydown", this.#handleKeyDown.bind(this));
|
|
3778
3824
|
|
|
3779
|
-
|
|
3780
|
-
if (this.preventImmediateReopen) { return }
|
|
3781
|
-
|
|
3782
|
-
this.triggerButton = triggerButton;
|
|
3783
|
-
this.#positionDialog();
|
|
3784
|
-
this.dialog.show();
|
|
3785
|
-
|
|
3786
|
-
this.#setupClickOutsideHandler();
|
|
3825
|
+
this.#setTabIndexValues();
|
|
3787
3826
|
}
|
|
3788
3827
|
|
|
3789
|
-
|
|
3790
|
-
this
|
|
3828
|
+
disconnectedCallback() {
|
|
3829
|
+
this.#removeClickOutsideHandler();
|
|
3830
|
+
this.container.removeEventListener("keydown", this.#handleKeyDown.bind(this));
|
|
3791
3831
|
}
|
|
3792
3832
|
|
|
3793
3833
|
get toolbar() {
|
|
@@ -3798,32 +3838,32 @@ class ToolbarDialog extends HTMLElement {
|
|
|
3798
3838
|
return this.toolbar.editor
|
|
3799
3839
|
}
|
|
3800
3840
|
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
#registerHandlers() {
|
|
3804
|
-
this.#setupKeydownHandler();
|
|
3805
|
-
this.dialog.addEventListener("cancel", this.#handleCancel.bind(this));
|
|
3806
|
-
this.dialog.addEventListener("close", this.#handleClose.bind(this));
|
|
3841
|
+
close() {
|
|
3842
|
+
this.container.removeAttribute("open");
|
|
3807
3843
|
}
|
|
3808
3844
|
|
|
3809
|
-
#
|
|
3810
|
-
this
|
|
3811
|
-
|
|
3812
|
-
|
|
3845
|
+
#handleToggle(event) {
|
|
3846
|
+
if (this.container.open) {
|
|
3847
|
+
this.#handleOpen(event.target);
|
|
3848
|
+
} else {
|
|
3849
|
+
this.#handleClose();
|
|
3850
|
+
}
|
|
3813
3851
|
}
|
|
3814
3852
|
|
|
3815
|
-
#
|
|
3816
|
-
this.
|
|
3817
|
-
|
|
3853
|
+
#handleOpen(trigger) {
|
|
3854
|
+
this.trigger = trigger;
|
|
3855
|
+
this.#interactiveElements[0].focus();
|
|
3856
|
+
this.#setupClickOutsideHandler();
|
|
3818
3857
|
}
|
|
3819
3858
|
|
|
3820
|
-
#
|
|
3821
|
-
|
|
3822
|
-
this
|
|
3859
|
+
#handleClose() {
|
|
3860
|
+
this.trigger = null;
|
|
3861
|
+
this.#removeClickOutsideHandler();
|
|
3862
|
+
this.editor.focus();
|
|
3823
3863
|
}
|
|
3824
3864
|
|
|
3825
3865
|
#setupClickOutsideHandler() {
|
|
3826
|
-
if (this
|
|
3866
|
+
if (this.clickOutsideHandler) return
|
|
3827
3867
|
|
|
3828
3868
|
this.clickOutsideHandler = this.#handleClickOutside.bind(this);
|
|
3829
3869
|
document.addEventListener("click", this.clickOutsideHandler, true);
|
|
@@ -3837,22 +3877,7 @@ class ToolbarDialog extends HTMLElement {
|
|
|
3837
3877
|
}
|
|
3838
3878
|
|
|
3839
3879
|
#handleClickOutside({ target }) {
|
|
3840
|
-
if (!this.
|
|
3841
|
-
|
|
3842
|
-
const isClickInsideDialog = this.dialog.contains(target);
|
|
3843
|
-
const isClickOnTrigger = this.triggerButton.contains(target);
|
|
3844
|
-
|
|
3845
|
-
if (!isClickInsideDialog && !isClickOnTrigger) {
|
|
3846
|
-
this.close();
|
|
3847
|
-
}
|
|
3848
|
-
}
|
|
3849
|
-
|
|
3850
|
-
#setupKeydownHandler() {
|
|
3851
|
-
if (!this.#browserHandlesClose) { this.addEventListener("keydown", this.#handleKeyDown.bind(this)); }
|
|
3852
|
-
}
|
|
3853
|
-
|
|
3854
|
-
get #browserHandlesClose() {
|
|
3855
|
-
return this.dialog.closedBy === "any"
|
|
3880
|
+
if (this.container.open && !this.container.contains(target)) this.close();
|
|
3856
3881
|
}
|
|
3857
3882
|
|
|
3858
3883
|
#handleKeyDown(event) {
|
|
@@ -3861,9 +3886,20 @@ class ToolbarDialog extends HTMLElement {
|
|
|
3861
3886
|
this.close();
|
|
3862
3887
|
}
|
|
3863
3888
|
}
|
|
3889
|
+
|
|
3890
|
+
async #setTabIndexValues() {
|
|
3891
|
+
await nextFrame();
|
|
3892
|
+
this.#interactiveElements.forEach((element) => {
|
|
3893
|
+
element.setAttribute("tabindex", 0);
|
|
3894
|
+
});
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3897
|
+
get #interactiveElements() {
|
|
3898
|
+
return Array.from(this.querySelectorAll("button, input"))
|
|
3899
|
+
}
|
|
3864
3900
|
}
|
|
3865
3901
|
|
|
3866
|
-
class
|
|
3902
|
+
class LinkDropdown extends ToolbarDropdown {
|
|
3867
3903
|
connectedCallback() {
|
|
3868
3904
|
super.connectedCallback();
|
|
3869
3905
|
this.input = this.querySelector("input");
|
|
@@ -3871,23 +3907,21 @@ class LinkDialog extends ToolbarDialog {
|
|
|
3871
3907
|
this.#registerHandlers();
|
|
3872
3908
|
}
|
|
3873
3909
|
|
|
3874
|
-
updateStateCallback() {
|
|
3875
|
-
this.input.value = this.#selectedLinkUrl;
|
|
3876
|
-
}
|
|
3877
|
-
|
|
3878
3910
|
#registerHandlers() {
|
|
3879
|
-
this.
|
|
3880
|
-
this.
|
|
3911
|
+
this.container.addEventListener("toggle", this.#handleToggle.bind(this));
|
|
3912
|
+
this.addEventListener("submit", this.#handleSubmit.bind(this));
|
|
3881
3913
|
this.querySelector("[value='unlink']").addEventListener("click", this.#handleUnlink.bind(this));
|
|
3882
3914
|
}
|
|
3883
3915
|
|
|
3884
|
-
#
|
|
3916
|
+
#handleToggle({ newState }) {
|
|
3917
|
+
this.input.value = this.#selectedLinkUrl;
|
|
3885
3918
|
this.input.required = newState === "open";
|
|
3886
3919
|
}
|
|
3887
3920
|
|
|
3888
3921
|
#handleSubmit(event) {
|
|
3889
3922
|
const command = event.submitter?.value;
|
|
3890
3923
|
this.editor.dispatchCommand(command, this.input.value);
|
|
3924
|
+
this.close();
|
|
3891
3925
|
}
|
|
3892
3926
|
|
|
3893
3927
|
#handleUnlink() {
|
|
@@ -3916,14 +3950,17 @@ class LinkDialog extends ToolbarDialog {
|
|
|
3916
3950
|
}
|
|
3917
3951
|
}
|
|
3918
3952
|
|
|
3919
|
-
|
|
3920
|
-
// supported by Safari yet: customElements.define("lexxy-link-dialog", LinkDialog, { extends: "dialog" })
|
|
3921
|
-
customElements.define("lexxy-link-dialog", LinkDialog);
|
|
3953
|
+
customElements.define("lexxy-link-dropdown", LinkDropdown);
|
|
3922
3954
|
|
|
3923
3955
|
const APPLY_HIGHLIGHT_SELECTOR = "button.lexxy-highlight-button";
|
|
3924
3956
|
const REMOVE_HIGHLIGHT_SELECTOR = "[data-command='removeHighlight']";
|
|
3925
3957
|
|
|
3926
|
-
|
|
3958
|
+
// Use Symbol instead of null since $getSelectionStyleValueForProperty
|
|
3959
|
+
// responds differently for backward selections if null is the default
|
|
3960
|
+
// see https://github.com/facebook/lexical/issues/8013
|
|
3961
|
+
const NO_STYLE = Symbol("no_style");
|
|
3962
|
+
|
|
3963
|
+
class HighlightDropdown extends ToolbarDropdown {
|
|
3927
3964
|
connectedCallback() {
|
|
3928
3965
|
super.connectedCallback();
|
|
3929
3966
|
|
|
@@ -3931,13 +3968,10 @@ class HighlightDialog extends ToolbarDialog {
|
|
|
3931
3968
|
this.#registerHandlers();
|
|
3932
3969
|
}
|
|
3933
3970
|
|
|
3934
|
-
updateStateCallback() {
|
|
3935
|
-
this.#updateColorButtonStates($getSelection());
|
|
3936
|
-
}
|
|
3937
|
-
|
|
3938
3971
|
#registerHandlers() {
|
|
3939
|
-
this.
|
|
3972
|
+
this.container.addEventListener("toggle", this.#handleToggle.bind(this));
|
|
3940
3973
|
this.#colorButtons.forEach(button => button.addEventListener("click", this.#handleColorButtonClick.bind(this)));
|
|
3974
|
+
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).addEventListener("click", this.#handleRemoveHighlightClick.bind(this));
|
|
3941
3975
|
}
|
|
3942
3976
|
|
|
3943
3977
|
#setUpButtons() {
|
|
@@ -3964,6 +3998,14 @@ class HighlightDialog extends ToolbarDialog {
|
|
|
3964
3998
|
return button
|
|
3965
3999
|
}
|
|
3966
4000
|
|
|
4001
|
+
#handleToggle({ newState }) {
|
|
4002
|
+
if (newState === "open") {
|
|
4003
|
+
this.editor.getEditorState().read(() => {
|
|
4004
|
+
this.#updateColorButtonStates($getSelection());
|
|
4005
|
+
});
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
|
|
3967
4009
|
#handleColorButtonClick(event) {
|
|
3968
4010
|
event.preventDefault();
|
|
3969
4011
|
|
|
@@ -3987,16 +4029,16 @@ class HighlightDialog extends ToolbarDialog {
|
|
|
3987
4029
|
#updateColorButtonStates(selection) {
|
|
3988
4030
|
if (!$isRangeSelection(selection)) { return }
|
|
3989
4031
|
|
|
3990
|
-
// Use
|
|
3991
|
-
const textColor = $getSelectionStyleValueForProperty(selection, "color",
|
|
3992
|
-
const backgroundColor = $getSelectionStyleValueForProperty(selection, "background-color",
|
|
4032
|
+
// Use non-"" default, so "" indicates mixed highlighting
|
|
4033
|
+
const textColor = $getSelectionStyleValueForProperty(selection, "color", NO_STYLE);
|
|
4034
|
+
const backgroundColor = $getSelectionStyleValueForProperty(selection, "background-color", NO_STYLE);
|
|
3993
4035
|
|
|
3994
4036
|
this.#colorButtons.forEach(button => {
|
|
3995
4037
|
const matchesSelection = button.dataset.value === textColor || button.dataset.value === backgroundColor;
|
|
3996
4038
|
button.setAttribute("aria-pressed", matchesSelection);
|
|
3997
4039
|
});
|
|
3998
4040
|
|
|
3999
|
-
const hasHighlight = textColor !==
|
|
4041
|
+
const hasHighlight = textColor !== NO_STYLE || backgroundColor !== NO_STYLE;
|
|
4000
4042
|
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).disabled = !hasHighlight;
|
|
4001
4043
|
}
|
|
4002
4044
|
|
|
@@ -4009,9 +4051,7 @@ class HighlightDialog extends ToolbarDialog {
|
|
|
4009
4051
|
}
|
|
4010
4052
|
}
|
|
4011
4053
|
|
|
4012
|
-
|
|
4013
|
-
// supported by Safari yet: customElements.define("lexxy-hightlight-dialog", HighlightDialog, { extends: "dialog" })
|
|
4014
|
-
customElements.define("lexxy-highlight-dialog", HighlightDialog);
|
|
4054
|
+
customElements.define("lexxy-highlight-dropdown", HighlightDropdown);
|
|
4015
4055
|
|
|
4016
4056
|
class BaseSource {
|
|
4017
4057
|
// Template method to override
|
|
@@ -4156,10 +4196,13 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
4156
4196
|
this.keyListeners = [];
|
|
4157
4197
|
}
|
|
4158
4198
|
|
|
4199
|
+
static observedAttributes = [ "connected" ]
|
|
4200
|
+
|
|
4159
4201
|
connectedCallback() {
|
|
4160
4202
|
this.source = this.#createSource();
|
|
4161
4203
|
|
|
4162
4204
|
this.#addTriggerListener();
|
|
4205
|
+
this.toggleAttribute("connected", true);
|
|
4163
4206
|
}
|
|
4164
4207
|
|
|
4165
4208
|
disconnectedCallback() {
|
|
@@ -4167,6 +4210,13 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
4167
4210
|
this.popoverElement = null;
|
|
4168
4211
|
}
|
|
4169
4212
|
|
|
4213
|
+
|
|
4214
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
4215
|
+
if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
|
|
4216
|
+
requestAnimationFrame(() => this.#reconnect());
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
|
|
4170
4220
|
get name() {
|
|
4171
4221
|
return this.getAttribute("name")
|
|
4172
4222
|
}
|
|
@@ -4536,6 +4586,11 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
4536
4586
|
this.#optionWasSelected();
|
|
4537
4587
|
}
|
|
4538
4588
|
}
|
|
4589
|
+
|
|
4590
|
+
#reconnect() {
|
|
4591
|
+
this.disconnectedCallback();
|
|
4592
|
+
this.connectedCallback();
|
|
4593
|
+
}
|
|
4539
4594
|
}
|
|
4540
4595
|
|
|
4541
4596
|
customElements.define("lexxy-prompt", LexicalPromptElement);
|
|
@@ -4578,6 +4633,11 @@ class CodeLanguagePicker extends HTMLElement {
|
|
|
4578
4633
|
const languages = { ...CODE_LANGUAGE_FRIENDLY_NAME_MAP };
|
|
4579
4634
|
|
|
4580
4635
|
if (!languages.ruby) languages.ruby = "Ruby";
|
|
4636
|
+
if (!languages.php) languages.php = "PHP";
|
|
4637
|
+
if (!languages.go) languages.go = "Go";
|
|
4638
|
+
if (!languages.bash) languages.bash = "Bash";
|
|
4639
|
+
if (!languages.json) languages.json = "JSON";
|
|
4640
|
+
if (!languages.diff) languages.diff = "Diff";
|
|
4581
4641
|
|
|
4582
4642
|
const sortedEntries = Object.entries(languages)
|
|
4583
4643
|
.sort(([ , a ], [ , b ]) => a.localeCompare(b));
|