@@ -5265,19 +5265,12 @@ class LexicalToolbarElement extends HTMLElement {
52655265 this.toggleAttribute("connected", true);
52665266 }
52675267
5268- get #dialogs() {
5269- const dialogButtons = this.querySelectorAll("[data-dialog-target]");
5270- const dialogTags = Array.from(dialogButtons).map(button => `lexxy-${button.dataset.dialogTarget}`);
5271- return Array.from(this.querySelectorAll(dialogTags))
5272- }
5273-
52745268 #bindButtons() {
52755269 this.addEventListener("click", this.#handleButtonClicked.bind(this));
52765270 }
52775271
52785272 #handleButtonClicked({ target }) {
52795273 this.#handleTargetClicked(target, "[data-command]", this.#dispatchButtonCommand.bind(this));
5280- this.#handleTargetClicked(target, "[data-dialog-target]", this.#toggleDialog.bind(this));
52815274 }
52825275
52835276 #handleTargetClicked(target, selector, callback) {
@@ -5292,27 +5285,6 @@ class LexicalToolbarElement extends HTMLElement {
52925285 this.editor.dispatchCommand(command, payload);
52935286 }
52945287
5295- // Not using popover because of CSS anchoring still not widely available.
5296- #toggleDialog(button) {
5297- const dialogTarget = button.dataset.dialogTarget;
5298- const dialog = this.querySelector("lexxy-" + dialogTarget);
5299- if (!dialog) return
5300-
5301- if (dialog.open) {
5302- dialog.close();
5303- } else {
5304- this.#closeOpenDialogs();
5305- dialog.show(button);
5306- }
5307- }
5308-
5309- #closeOpenDialogs() {
5310- const openDialogs = this.querySelectorAll("dialog[open]");
5311- openDialogs.forEach(openDialog => {
5312- openDialog.closest(".lexxy-dialog").close();
5313- });
5314- }
5315-
53165288 #bindHotkeys() {
53175289 this.editorElement.addEventListener("keydown", this.#handleHotkey);
53185290 }
@@ -5346,9 +5318,8 @@ class LexicalToolbarElement extends HTMLElement {
53465318 }
53475319
53485320 #assignButtonTabindex() {
5349- const baseTabIndex = parseInt(this.editorElement.editorContentElement.getAttribute("tabindex") ?? "0");
5350- this.#buttons.forEach((button, index) => {
5351- button.setAttribute("tabindex", `${baseTabIndex + index + 1}`);
5321+ this.#buttons.forEach((button) => {
5322+ button.setAttribute("tabindex", 0);
53525323 });
53535324 }
53545325
@@ -5492,17 +5463,21 @@ class LexicalToolbarElement extends HTMLElement {
54925463 }
54935464 }
54945465
5466+ #reconnect() {
5467+ this.disconnectedCallback();
5468+ this.connectedCallback();
5469+ }
5470+
54955471 get #buttons() {
5496- return Array.from(this.querySelectorAll(":scope > button"))
5472+ return Array.from(this.querySelectorAll(":scope > button, :scope > details summary "))
54975473 }
54985474
54995475 get #buttonsWithSeparator() {
55005476 return Array.from(this.querySelectorAll(":scope > button, :scope > [role=separator]"))
55015477 }
55025478
5503- #reconnect() {
5504- this.disconnectedCallback();
5505- this.connectedCallback();
5479+ get #dialogs() {
5480+ return Array.from(this.querySelectorAll(":scope > details .lexxy-dialog"))
55065481 }
55075482
55085483 static get defaultTemplate() {
@@ -5515,41 +5490,39 @@ class LexicalToolbarElement extends HTMLElement {
55155490 <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M17.1 4h-1.5l-3.2 16h1.5l-.4 2h-7l.4-2h1.5l3.2-16h-1.5l.4-2h7l-.4 2z"/></svg>
55165491 </button>
55175492
5518- <button class="lexxy-editor__toolbar-button" type="button" name="strikethrough" data-command="strikethrough" title="Strikethrough">
5493+ <button class="lexxy-editor__toolbar-button" role="button" type="button" name="strikethrough" data-command="strikethrough" title="Strikethrough">
55195494 <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
55205495 <path fill-rule="evenodd" clip-rule="evenodd" d="M4.70588 16.1591C4.81459 19.7901 7.48035 22 11.6668 22C15.9854 22 18.724 19.6296 18.724 15.8779C18.724 15.5007 18.6993 15.1427 18.6474 14.8066H14.3721C14.8637 15.2085 15.0799 15.7037 15.0799 16.3471C15.0799 17.7668 13.7532 18.7984 11.8113 18.7984C9.88053 18.7984 8.38582 17.7531 8.21659 16.1591H4.70588ZM5.23953 9.31962H9.88794C9.10723 8.88889 8.75888 8.33882 8.75888 7.57339C8.75888 6.13992 9.96576 5.18793 11.7631 5.18793C13.5852 5.18793 14.8761 6.1797 14.9959 7.81344H18.4102C18.3485 4.31824 15.8038 2 11.752 2C7.867 2 5.09129 4.35802 5.09129 7.92044C5.09129 8.41838 5.14071 8.88477 5.23953 9.31962ZM2.23529 10.6914C1.90767 10.6914 1.59347 10.8359 1.36181 11.0931C1.13015 11.3504 1 11.6993 1 12.0631C1 12.4269 1.13015 12.7758 1.36181 13.0331C1.59347 13.2903 1.90767 13.4348 2.23529 13.4348H20.7647C21.0923 13.4348 21.4065 13.2903 21.6382 13.0331C21.8699 12.7758 22 12.4269 22 12.0631C22 11.6993 21.8699 11.3504 21.6382 11.0931C21.4065 10.8359 21.0923 10.6914 20.7647 10.6914H2.23529Z"/>
55215496 </svg>
55225497 </button>
55235498
5524- <lexxy-highlight-dialog class="lexxy-dialog lexxy-highlight-dialog">
5525- <dialog class="highlight-dialog">
5499+ <details class="lexxy-editor__has-details" name="lexxy-dialog" title="Color highlight" data-dialog-target="highlight-dialog">
5500+ <summary role="button" class="lexxy-editor__toolbar-button" name="highlight">
5501+ <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>
5502+ </summary>
5503+ <lexxy-highlight-dialog class="lexxy-dialog lexxy-highlight-dialog">
55265504 <div class="lexxy-highlight-dialog-content">
55275505 <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>
55285506 <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>
55295507 <button data-command="removeHighlight" class="lexxy-highlight-dialog-reset">Remove all coloring</button>
55305508 </div>
5531- </dialog>
5532- </lexxy-highlight-dialog>
5533-
5534- <button class="lexxy-editor__toolbar-button" type="button" name="highlight" title="Color highlight" data-dialog-target="highlight-dialog">
5535- <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>
5536- </button>
5509+ </lexxy-highlight-dialog>
5510+ </details>
55375511
5538- <lexxy-link-dialog class="lexxy-dialog lexxy-link-dialog">
5539- <dialog class="link-dialog">
5512+ <details class="lexxy-editor__has-details" name="lexxy-dialog" title="Link" data-hotkey="cmd+k ctrl+k">
5513+ <summary role="button" class="lexxy-editor__toolbar-button" name="link">
5514+ <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>
5515+ </summary>
5516+ <lexxy-link-dialog class="lexxy-dialog lexxy-link-dialog">
55405517 <form method="dialog">
55415518 <input type="url" placeholder="Enter a URL…" class="input" required>
55425519 <div class="lexxy-dialog-actions">
55435520 <button type="submit" class="btn" value="link">Link</button>
55445521 <button type="button" class="btn" value="unlink">Unlink</button>
55455522 </div>
55465523 </form>
5547- </dialog>
5548- </lexxy-link-dialog>
5549-
5550- <button class="lexxy-editor__toolbar-button" type="button" name="link" title="Link" data-dialog-target="link-dialog" data-hotkey="cmd+k ctrl+k">
5551- <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>
5552- </button>
5524+ </lexxy-link-dialog>
5525+ </details>
55535526
55545527 <button class="lexxy-editor__toolbar-button" type="button" name="quote" data-command="insertQuoteBlock" title="Quote">
55555528 <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>
@@ -9565,6 +9538,10 @@ class LexicalEditorElement extends HTMLElement {
95659538 return this.getAttribute("attachments") !== "false"
95669539 }
95679540
9541+ get contentTabIndex() {
9542+ return parseInt(this.editorContentElement?.getAttribute("tabindex") ?? "0")
9543+ }
9544+
95689545 focus() {
95699546 this.editor.focus();
95709547 }
@@ -9887,33 +9864,21 @@ customElements.define("lexxy-editor", LexicalEditorElement);
98879864
98889865class ToolbarDialog extends HTMLElement {
98899866 connectedCallback() {
9890- this.dialog = this.querySelector("dialog");
9891- if ("closedBy" in this.dialog.constructor.prototype) {
9892- this.dialog.closedBy = "any";
9893- }
9894- this.#registerHandlers();
9867+ this.container = this.closest("details");
9868+
9869+ this.container.addEventListener("toggle", this.#handleToggle.bind(this));
9870+ this.container.addEventListener("keydown", this.#handleKeyDown.bind(this));
9871+
9872+ this.#assignTabIndexes();
98959873 }
98969874
98979875 disconnectedCallback() {
98989876 this.#removeClickOutsideHandler();
9877+ this.container.removeEventListener("keydown", this.#handleKeyDown.bind(this));
98999878 }
99009879
99019880 updateStateCallback() { }
99029881
9903- show(triggerButton) {
9904- if (this.preventImmediateReopen) { return }
9905-
9906- this.triggerButton = triggerButton;
9907- this.#positionDialog();
9908- this.dialog.show();
9909-
9910- this.#setupClickOutsideHandler();
9911- }
9912-
9913- close() {
9914- this.dialog.close();
9915- }
9916-
99179882 get toolbar() {
99189883 return this.closest("lexxy-toolbar")
99199884 }
@@ -9922,32 +9887,44 @@ class ToolbarDialog extends HTMLElement {
99229887 return this.toolbar.editor
99239888 }
99249889
9925- get open() { return this.dialog. open }
9890+ get open() { return this.hasAttribute(" open") }
99269891
9927- #registerHandlers( ) {
9928- this.#setupKeydownHandler() ;
9929- this.dialog.addEventListener("cancel", this.#handleCancel.bind(this));
9930- this.dialog.addEventListener("close", this.#handleClose.bind(this) );
9892+ open(triggerButton ) {
9893+ this.triggerButton = triggerButton ;
9894+
9895+ this.#setupClickOutsideHandler( );
99319896 }
99329897
9933- #handleClose () {
9898+ close () {
99349899 this.#removeClickOutsideHandler();
99359900 this.triggerButton = null;
99369901 this.editor.focus();
9902+
9903+ this.container.removeAttribute("open");
9904+ }
9905+
9906+ #handleToggle(event) {
9907+ if (this.container.open) {
9908+ this.open(event.target);
9909+ } else {
9910+ this.close();
9911+ }
99379912 }
99389913
9939- #handleCancel() {
9940- this.preventImmediateReopen = true;
9941- requestAnimationFrame(() => this.preventImmediateReopen = undefined);
9914+ #assignTabIndexes() {
9915+ requestAnimationFrame(() => {
9916+ this.#interactiveElements.forEach((element) => {
9917+ element.setAttribute("tabindex", 0);
9918+ });
9919+ });
99429920 }
99439921
9944- #positionDialog() {
9945- const left = this.triggerButton.offsetLeft;
9946- this.dialog.style.insetInlineStart = `${left}px`;
9922+ get #interactiveElements() {
9923+ return Array.from(this.querySelectorAll("button, input"))
99479924 }
99489925
99499926 #setupClickOutsideHandler() {
9950- if (this.#browserHandlesClose || this. clickOutsideHandler) return
9927+ if (this.clickOutsideHandler) return
99519928
99529929 this.clickOutsideHandler = this.#handleClickOutside.bind(this);
99539930 document.addEventListener("click", this.clickOutsideHandler, true);
@@ -9961,24 +9938,16 @@ class ToolbarDialog extends HTMLElement {
99619938 }
99629939
99639940 #handleClickOutside({ target }) {
9964- if (!this.dialog .open) return
9941+ if (!this.container .open) return
99659942
9966- const isClickInsideDialog = this.dialog. contains(target);
9943+ const isClickInsideDialog = this.contains(target);
99679944 const isClickOnTrigger = this.triggerButton.contains(target);
99689945
99699946 if (!isClickInsideDialog && !isClickOnTrigger) {
99709947 this.close();
99719948 }
99729949 }
99739950
9974- #setupKeydownHandler() {
9975- if (!this.#browserHandlesClose) { this.addEventListener("keydown", this.#handleKeyDown.bind(this)); }
9976- }
9977-
9978- get #browserHandlesClose() {
9979- return this.dialog.closedBy === "any"
9980- }
9981-
99829951 #handleKeyDown(event) {
99839952 if (event.key === "Escape") {
99849953 event.stopPropagation();
@@ -10000,8 +9969,8 @@ class LinkDialog extends ToolbarDialog {
100009969 }
100019970
100029971 #registerHandlers() {
10003- this.dialog. addEventListener("beforetoggle", this.#handleBeforeToggle.bind(this));
10004- this.dialog. addEventListener("submit", this.#handleSubmit.bind(this));
9972+ this.addEventListener("beforetoggle", this.#handleBeforeToggle.bind(this));
9973+ this.addEventListener("submit", this.#handleSubmit.bind(this));
100059974 this.querySelector("[value='unlink']").addEventListener("click", this.#handleUnlink.bind(this));
100069975 }
100079976
0 commit comments