lexxy 0.9.32 → 1.0.0

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.
@@ -7603,10 +7603,6 @@ class Configuration {
7603
7603
  }
7604
7604
  }
7605
7605
 
7606
- function range(from, to) {
7607
- return [ ...Array(1 + to - from).keys() ].map(i => i + from)
7608
- }
7609
-
7610
7606
  const global$1 = new Configuration({
7611
7607
  attachmentTagName: "action-text-attachment",
7612
7608
  attachmentContentTypeNamespace: "actiontext",
@@ -7627,8 +7623,28 @@ const presets = new Configuration({
7627
7623
  headings: [ "h2", "h3", "h4" ],
7628
7624
  highlight: {
7629
7625
  buttons: {
7630
- color: range(1, 9).map(n => `var(--highlight-${n})`),
7631
- "background-color": range(1, 9).map(n => `var(--highlight-bg-${n})`),
7626
+ color: [
7627
+ { value: "var(--highlight-1)", label: "Yellow" },
7628
+ { value: "var(--highlight-2)", label: "Orange" },
7629
+ { value: "var(--highlight-3)", label: "Red" },
7630
+ { value: "var(--highlight-4)", label: "Magenta" },
7631
+ { value: "var(--highlight-5)", label: "Purple" },
7632
+ { value: "var(--highlight-6)", label: "Blue" },
7633
+ { value: "var(--highlight-7)", label: "Green" },
7634
+ { value: "var(--highlight-8)", label: "Sand" },
7635
+ { value: "var(--highlight-9)", label: "Gray" },
7636
+ ],
7637
+ "background-color": [
7638
+ { value: "var(--highlight-bg-1)", label: "Yellow" },
7639
+ { value: "var(--highlight-bg-2)", label: "Orange" },
7640
+ { value: "var(--highlight-bg-3)", label: "Red" },
7641
+ { value: "var(--highlight-bg-4)", label: "Magenta" },
7642
+ { value: "var(--highlight-bg-5)", label: "Purple" },
7643
+ { value: "var(--highlight-bg-6)", label: "Blue" },
7644
+ { value: "var(--highlight-bg-7)", label: "Green" },
7645
+ { value: "var(--highlight-bg-8)", label: "Sand" },
7646
+ { value: "var(--highlight-bg-9)", label: "Gray" },
7647
+ ],
7632
7648
  },
7633
7649
  permit: {
7634
7650
  color: [],
@@ -8097,11 +8113,45 @@ function checkVisibility(element, options) {
8097
8113
  }
8098
8114
  }
8099
8115
 
8100
- function handleRollingTabIndex(elements, event) {
8116
+ // Keyboard and programmatic clicks carry a synthetic pointer.
8117
+ function isKeyboardActivation(event) {
8118
+ return event instanceof PointerEvent && event.pointerId === -1
8119
+ }
8120
+
8121
+ function trapFocusAtTabBoundary(container, event) {
8122
+ if (event.key !== "Tab") return
8123
+
8124
+ const tabStops = Array.from(container.querySelectorAll("a[href], area[href], button, input:not([type='hidden']), select, textarea, iframe, object, embed, [contenteditable]:not([contenteditable='false']), [tabindex], summary, audio[controls], video[controls]"))
8125
+ .filter(element => element.tabIndex >= 0 && !element.matches(":disabled") && !element.closest("[inert]") && isActiveAndVisible(element))
8126
+ .sort((first, second) => {
8127
+ if (first.tabIndex > 0 && second.tabIndex > 0) {
8128
+ return first.tabIndex - second.tabIndex
8129
+ } else if (first.tabIndex > 0) {
8130
+ return -1
8131
+ } else if (second.tabIndex > 0) {
8132
+ return 1
8133
+ } else {
8134
+ return 0
8135
+ }
8136
+ });
8137
+
8138
+ const firstTabStop = tabStops[0];
8139
+ const lastTabStop = tabStops.at(-1);
8140
+
8141
+ if (event.shiftKey && document.activeElement === firstTabStop) {
8142
+ event.preventDefault();
8143
+ lastTabStop.focus();
8144
+ } else if (!event.shiftKey && document.activeElement === lastTabStop) {
8145
+ event.preventDefault();
8146
+ firstTabStop.focus();
8147
+ }
8148
+ }
8149
+
8150
+ function handleRollingTabIndex(elements, event, { orientation = "horizontal", wrap = false } = {}) {
8101
8151
  const previousActiveElement = document.activeElement;
8102
8152
 
8103
8153
  if (elements.includes(previousActiveElement)) {
8104
- const finder = new NextElementFinder(elements, event.key);
8154
+ const finder = new NextElementFinder(elements, event.key, { orientation, wrap });
8105
8155
 
8106
8156
  if (finder.selectNext(previousActiveElement)) {
8107
8157
  event.preventDefault();
@@ -8110,9 +8160,11 @@ function handleRollingTabIndex(elements, event) {
8110
8160
  }
8111
8161
 
8112
8162
  class NextElementFinder {
8113
- constructor(elements, key) {
8163
+ constructor(elements, key, { orientation, wrap }) {
8114
8164
  this.elements = elements;
8115
8165
  this.key = key;
8166
+ this.orientation = orientation;
8167
+ this.wrap = wrap;
8116
8168
  }
8117
8169
 
8118
8170
  selectNext(fromElement) {
@@ -8129,23 +8181,36 @@ class NextElementFinder {
8129
8181
  }
8130
8182
 
8131
8183
  #findNextElement(fromElement) {
8132
- switch (this.key) {
8133
- case "ArrowRight":
8134
- case "ArrowDown":
8184
+ switch (this.#directionFor(this.key)) {
8185
+ case "next":
8135
8186
  return this.#findNextSibling(fromElement)
8136
8187
 
8137
- case "ArrowLeft":
8138
- case "ArrowUp":
8188
+ case "previous":
8139
8189
  return this.#findPreviousSibling(fromElement)
8140
8190
 
8141
- case "Home":
8191
+ case "first":
8142
8192
  return this.#findFirst()
8143
8193
 
8144
- case "End":
8194
+ case "last":
8145
8195
  return this.#findLast()
8146
8196
  }
8147
8197
  }
8148
8198
 
8199
+ #directionFor(key) {
8200
+ if (key === "Home") return "first"
8201
+ if (key === "End") return "last"
8202
+ if (this.#nextKeys.includes(key)) return "next"
8203
+ if (this.#previousKeys.includes(key)) return "previous"
8204
+ }
8205
+
8206
+ get #nextKeys() {
8207
+ return this.orientation === "both" ? [ "ArrowRight", "ArrowDown" ] : [ "ArrowRight" ]
8208
+ }
8209
+
8210
+ get #previousKeys() {
8211
+ return this.orientation === "both" ? [ "ArrowLeft", "ArrowUp" ] : [ "ArrowLeft" ]
8212
+ }
8213
+
8149
8214
  #findFirst(elements = this.elements) {
8150
8215
  return elements.find(isActiveAndVisible)
8151
8216
  }
@@ -8156,12 +8221,20 @@ class NextElementFinder {
8156
8221
 
8157
8222
  #findNextSibling(element) {
8158
8223
  const afterElements = this.elements.slice(this.#indexOf(element) + 1);
8159
- return this.#findFirst(afterElements)
8224
+ return this.#findFirst(afterElements) ?? this.#wrapToFirst()
8160
8225
  }
8161
8226
 
8162
8227
  #findPreviousSibling(element) {
8163
8228
  const beforeElements = this.elements.slice(0, this.#indexOf(element));
8164
- return this.#findLast(beforeElements)
8229
+ return this.#findLast(beforeElements) ?? this.#wrapToLast()
8230
+ }
8231
+
8232
+ #wrapToFirst() {
8233
+ return this.wrap ? this.#findFirst() : undefined
8234
+ }
8235
+
8236
+ #wrapToLast() {
8237
+ return this.wrap ? this.#findLast() : undefined
8165
8238
  }
8166
8239
 
8167
8240
  #indexOf(element) {
@@ -8182,29 +8255,29 @@ class NextElementFinder {
8182
8255
 
8183
8256
  var ToolbarIcons = {
8184
8257
  "bold":
8185
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8258
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8186
8259
  <path fill-rule="evenodd" clip-rule="evenodd" d="M9.05273 1.88232C10.6866 1.88237 12.0033 2.20353 12.9529 2.89673L13.1272 3.0293C13.974 3.70864 14.4008 4.63245 14.4009 5.76562C14.4008 6.49354 14.2316 7.15281 13.8845 7.73145C13.6683 8.09188 13.3997 8.40162 13.0818 8.66016C13.5902 8.92606 14.0196 9.28599 14.3635 9.74121C14.8586 10.3834 15.0945 11.1743 15.0945 12.0879C15.0944 13.3698 14.5922 14.3931 13.5879 15.1106L13.5857 15.1128C12.5967 15.805 11.196 16.125 9.43799 16.125H3.10547V1.88232L9.05273 1.88232ZM6.36108 13.4084H9.28418C10.224 13.4084 10.8634 13.2491 11.2581 12.9851C11.6259 12.7389 11.8198 12.3768 11.8198 11.8367C11.8197 11.2968 11.6259 10.9351 11.2581 10.689C10.8634 10.425 10.2241 10.2649 9.28418 10.2649H6.36108V13.4084ZM6.36108 7.56812H8.78247C9.5163 7.56809 10.0547 7.45371 10.429 7.25757L10.5791 7.16895C10.9438 6.92178 11.1255 6.57934 11.1255 6.09302C11.1254 5.59017 10.9414 5.25227 10.5835 5.02002L10.5784 5.01636L10.5732 5.01343C10.1994 4.75387 9.61878 4.59818 8.78247 4.59814H6.36108V7.56812Z"/>
8187
8260
  </svg>`,
8188
8261
 
8189
8262
  "italic":
8190
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8263
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8191
8264
  <path d="M14.1379 3.91187L14.1086 4.06421H11.4668L9.49805 13.9431H12.0981L11.7473 15.7852L11.7188 15.9375H4.16675L4.51758 14.0955L4.54614 13.9431H7.18799L9.17505 4.06421H6.55664L6.90747 2.22217L6.93677 2.06982H14.4888L14.1379 3.91187Z"/>
8192
8265
  </svg>`,
8193
8266
 
8194
8267
  "strikethrough":
8195
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8268
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8196
8269
  <path d="M14.3723 11.8015C14.3771 11.8858 14.3811 11.9756 14.3811 12.0681C14.3811 12.811 14.1777 13.4959 13.7725 14.1174L13.7717 14.1189C13.3624 14.7329 12.7463 15.2162 11.9377 15.5742L11.9348 15.5757C11.1214 15.9223 10.1306 16.092 8.96997 16.092C7.9356 16.092 6.93308 15.9348 5.96338 15.6204L5.96045 15.6189C5.00593 15.292 4.24112 14.8699 3.67676 14.3459L3.57568 14.2522L3.63501 14.1277L4.45605 12.397L4.64282 12.5654C5.13492 13.0083 5.76733 13.3759 6.54492 13.6648C7.33475 13.9406 8.14322 14.0786 8.96997 14.0786C10.0731 14.0786 10.8638 13.8932 11.3708 13.5513C11.8757 13.1982 12.1172 12.7464 12.1172 12.1838C12.1172 12.0662 12.1049 11.9556 12.0828 11.8513L12.0344 11.625H14.3621L14.3723 11.8015Z"/>
8197
8270
  <path d="M9.2981 1.91602C10.111 1.91604 10.9109 2.02122 11.6975 2.23096C12.4855 2.44111 13.1683 2.74431 13.7417 3.14429L13.8655 3.23071L13.8083 3.36987L13.1726 4.91235L13.0869 5.1189L12.8987 4.99878C12.3487 4.64881 11.761 4.38633 11.1365 4.21143L11.1328 4.20996C10.585 4.04564 10.0484 3.95419 9.52295 3.93384L9.2981 3.92944C8.22329 3.92944 7.44693 4.12611 6.94043 4.49121C6.44619 4.85665 6.20874 5.31616 6.20874 5.88135L6.21533 6.03296C6.24495 6.37662 6.37751 6.65526 6.61011 6.87964L6.72144 6.97632C6.98746 7.19529 7.30625 7.37584 7.68018 7.51538L8.05151 7.63184C8.45325 7.75061 8.94669 7.87679 9.53247 8.01123L9.53467 8.01196C10.1213 8.15305 10.6426 8.29569 11.0991 8.4375H15C15.5178 8.4375 15.9375 8.85723 15.9375 9.375C15.9375 9.89277 15.5178 10.3125 15 10.3125H3C2.48223 10.3125 2.0625 9.89277 2.0625 9.375C2.0625 8.85723 2.48223 8.4375 3 8.4375H4.93726C4.83783 8.34526 4.74036 8.24896 4.64795 8.146L4.64502 8.14233C4.1721 7.58596 3.94482 6.85113 3.94482 5.95825C3.94483 5.20441 4.14059 4.51965 4.53369 3.90967L4.53516 3.90747C4.94397 3.29427 5.55262 2.81114 6.34863 2.45288C7.15081 2.0919 8.13683 1.91602 9.2981 1.91602Z"/>
8198
8271
  </svg>`,
8199
8272
 
8200
8273
  "underline":
8201
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8274
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8202
8275
  <path d="M14 14C14.5523 14 15 14.4477 15 15C15 15.5523 14.5523 16 14 16H4C3.44772 16 3 15.5523 3 15C3 14.4477 3.44772 14 4 14H14Z"/>
8203
8276
  <path d="M12.625 1.59375C13.25 1.59375 13.625 1.97656 13.625 2.64062V9.02344C13.625 11.4844 11.8516 13.1875 8.99219 13.1875C6.14062 13.1875 4.35938 11.4844 4.35938 9.02344V2.64062C4.35938 1.97656 4.74219 1.59375 5.36719 1.59375C6 1.59375 6.375 1.97656 6.375 2.64062V8.84375C6.375 10.3828 7.32031 11.4297 8.99219 11.4297C10.6641 11.4297 11.6172 10.3828 11.6172 8.84375V2.64062C11.6172 1.97656 11.9922 1.59375 12.625 1.59375Z"/>
8204
8277
  </svg>`,
8205
8278
 
8206
8279
  "heading":
8207
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8280
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8208
8281
  <path d="M11.5 2C12.0523 2 12.5 2.44772 12.5 3V3.5C12.5 4.05228 12.0523 4.5 11.5 4.5H8V15C8 15.5523 7.55228 16 7 16H6.5C5.94772 16 5.5 15.5523 5.5 15V4.5H2C1.44772 4.5 1 4.05228 1 3.5V3C1 2.44772 1.44772 2 2 2H11.5ZM16 7C16.5523 7 17 7.44772 17 8V8.5C17 9.05228 16.5523 9.5 16 9.5H15V15C15 15.5523 14.5523 16 14 16H13.5C12.9477 16 12.5 15.5523 12.5 15V9.5H11.5C10.9477 9.5 10.5 9.05228 10.5 8.5V8C10.5 7.44772 10.9477 7 11.5 7H16Z"/>
8209
8282
  </svg>`,
8210
8283
 
@@ -8214,17 +8287,17 @@ var ToolbarIcons = {
8214
8287
  </svg>`,
8215
8288
 
8216
8289
  "h2":
8217
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8290
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8218
8291
  <path d="M8.12207 4.30078C8.84668 4.30078 9.25684 4.74512 9.25684 5.51758V12.5518C9.25677 13.3241 8.84662 13.7686 8.12207 13.7686C7.39752 13.7686 6.9942 13.3309 6.99414 12.5518V9.87207H3.56934V12.5518C3.56927 13.3241 3.15912 13.7686 2.43457 13.7686C1.71002 13.7686 1.3067 13.3309 1.30664 12.5518V5.51758C1.30664 4.73828 1.70996 4.30078 2.43457 4.30078C3.15918 4.30078 3.56934 4.74512 3.56934 5.51758V8.07422H6.99414V5.51758C6.99414 4.73828 7.39746 4.30078 8.12207 4.30078ZM13.6445 4.19824C15.5244 4.19824 16.8984 5.34668 16.8984 6.91211C16.8984 7.8759 16.4335 8.7237 15.292 9.84473L13.3438 11.8135V11.9092H16.1875C16.8232 11.9092 17.2197 12.251 17.2197 12.8115C17.2196 13.3651 16.83 13.7002 16.1875 13.7002H11.5117C10.8487 13.7002 10.4112 13.3241 10.4111 12.75C10.4111 12.3399 10.6368 11.9843 11.3203 11.3145L13.6855 8.88086C14.4169 8.13583 14.7245 7.64349 14.7246 7.12402C14.7246 6.4541 14.2393 6.00293 13.5215 6.00293C12.9404 6.00293 12.5166 6.29688 12.2158 6.90527C11.9151 7.37002 11.6552 7.54785 11.2588 7.54785C10.7188 7.54785 10.3429 7.17861 10.3428 6.65918C10.3428 5.3877 11.7783 4.19824 13.6445 4.19824Z"/>
8219
8292
  </svg>`,
8220
8293
 
8221
8294
  "h3":
8222
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8295
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8223
8296
  <path d="M13.5967 4.19824C15.5928 4.19824 16.9873 5.23047 16.9873 6.7002C16.9872 7.705 16.2421 8.60059 15.2988 8.7168V8.86719C16.4199 8.94923 17.2607 9.89942 17.2607 11.0889C17.2606 12.7362 15.7362 13.9053 13.583 13.9053C11.6827 13.9053 10.1925 12.873 10.1924 11.7041C10.1924 11.1846 10.5547 10.8154 11.0537 10.8154C11.3818 10.8154 11.6553 10.9727 11.9629 11.3555C12.3799 11.9159 12.92 12.2031 13.583 12.2031C14.4853 12.2031 15.0731 11.7313 15.0732 11C15.0732 10.2754 14.4785 9.7832 13.5898 9.7832H13.0361C12.5645 9.7832 12.2159 9.4208 12.2158 8.92188C12.2158 8.44336 12.5576 8.07422 13.0361 8.07422H13.5693C14.3075 8.07422 14.8544 7.60928 14.8545 6.97363C14.8545 6.33789 14.3213 5.90039 13.5557 5.90039C12.9678 5.90039 12.5029 6.16016 12.0859 6.71387C11.8399 7.03508 11.5527 7.17871 11.1973 7.17871C10.671 7.17871 10.295 6.82314 10.2949 6.31738C10.2949 5.18945 11.751 4.19824 13.5967 4.19824ZM8.0332 4.30078C8.75781 4.30078 9.16797 4.74512 9.16797 5.51758V12.5518C9.1679 13.3241 8.75776 13.7686 8.0332 13.7686C7.30865 13.7686 6.90534 13.3309 6.90527 12.5518V9.87207H3.48047V12.5518C3.4804 13.3241 3.07026 13.7686 2.3457 13.7686C1.62115 13.7686 1.21784 13.3309 1.21777 12.5518V5.51758C1.21777 4.73828 1.62109 4.30078 2.3457 4.30078C3.07031 4.30078 3.48047 4.74512 3.48047 5.51758V8.07422H6.90527V5.51758C6.90527 4.73828 7.30859 4.30078 8.0332 4.30078Z"/>
8224
8297
  </svg>`,
8225
8298
 
8226
8299
  "h4":
8227
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8300
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8228
8301
  <path d="M14.6357 4.22559C15.7432 4.22559 16.4336 4.80664 16.4336 5.73633V10.3164H16.7275C17.2881 10.3164 17.6436 10.6787 17.6436 11.2256C17.6435 11.7655 17.3017 12.1006 16.7275 12.1006H16.4336V12.6611C16.4335 13.3515 16.0234 13.7891 15.374 13.7891C14.7247 13.7891 14.3282 13.3583 14.3281 12.6611V12.1006H11.04C10.2335 12.1006 9.76863 11.6766 9.76855 10.918C9.76855 10.5762 9.85064 10.3026 10.1104 9.74219C10.7666 8.42289 11.5733 7.0146 12.5713 5.54492C13.2549 4.56738 13.7812 4.22559 14.6357 4.22559ZM7.88965 4.30078C8.61426 4.30078 9.02441 4.74512 9.02441 5.51758V12.5518C9.02435 13.3241 8.6142 13.7686 7.88965 13.7686C7.1651 13.7686 6.76178 13.3309 6.76172 12.5518V9.87207H3.33691V12.5518C3.33685 13.3241 2.9267 13.7686 2.20215 13.7686C1.4776 13.7686 1.07428 13.3309 1.07422 12.5518V5.51758C1.07422 4.73828 1.47754 4.30078 2.20215 4.30078C2.92676 4.30078 3.33691 4.74512 3.33691 5.51758V8.07422H6.76172V5.51758C6.76172 4.73828 7.16504 4.30078 7.88965 4.30078ZM14.2188 6.07812C13.6035 7.02841 12.2158 9.48929 11.7988 10.2686V10.3164H14.3281V6.07812H14.2188Z"/>
8229
8302
  </svg>`,
8230
8303
 
@@ -8239,44 +8312,44 @@ var ToolbarIcons = {
8239
8312
  </svg>`,
8240
8313
 
8241
8314
  "paragraph":
8242
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8315
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8243
8316
  <path d="M9 12C9.55228 12 10 12.4477 10 13C10 13.5523 9.55228 14 9 14H3C2.44772 14 2 13.5523 2 13C2 12.4477 2.44772 12 3 12H9ZM15 8C15.5523 8 16 8.44772 16 9C16 9.55228 15.5523 10 15 10H3C2.44772 10 2 9.55228 2 9C2 8.44772 2.44772 8 3 8H15ZM15 4C15.5523 4 16 4.44772 16 5C16 5.55228 15.5523 6 15 6H3C2.44772 6 2 5.55228 2 5C2 4.44772 2.44772 4 3 4H15Z"/>
8244
8317
  </svg>`,
8245
8318
 
8246
8319
  "clearFormatting":
8247
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8320
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8248
8321
  <path d="M10.0607 2.07533C10.8417 1.29432 12.1078 1.2943 12.8888 2.07533L16.424 5.61049C17.205 6.39154 17.205 7.65854 16.424 8.43959L9.44937 15.4142C9.07435 15.7891 8.5656 16.0001 8.03531 16.0001H5.0148C4.55074 16.0001 4.10309 15.8385 3.74722 15.547L3.60074 15.4142L1.57534 13.3888C0.79431 12.6078 0.794336 11.3417 1.57534 10.5607L10.0607 2.07533ZM2.98941 11.9747L5.0148 14.0001H8.03531L9.71792 12.3165L6.18179 8.78139L2.98941 11.9747Z"/>
8249
8322
  </svg>`,
8250
8323
 
8251
8324
  "highlight":
8252
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8325
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8253
8326
  <path d="M16.4564 14.4272C17.1356 15.5592 16.3204 17.0002 15.0003 17.0004C13.68 17.0004 12.864 15.5593 13.5433 14.4272L15.0003 12.0004L16.4564 14.4272ZM5.1214 1.70746C5.51192 1.31693 6.14494 1.31693 6.53546 1.70746L9.7171 4.8891L13.2532 8.42426C14.2295 9.40056 14.2295 10.9841 13.2532 11.9604L9.7171 15.4955C8.74078 16.4718 7.15822 16.4718 6.18195 15.4955L2.64679 11.9604C1.67048 10.9841 1.67048 9.40057 2.64679 8.42426L6.18195 4.8891C6.30299 4.76805 6.43323 4.66177 6.57062 4.57074L5.1214 3.12152C4.73091 2.73104 4.73099 2.09799 5.1214 1.70746ZM8.30304 6.30316C8.10776 6.10815 7.79119 6.10799 7.59601 6.30316L4.06085 9.83929L3.9964 9.91742C3.88661 10.0838 3.88645 10.3019 3.9964 10.4682L4.02277 10.5004H11.8763C12.0312 10.3043 12.02 10.0205 11.8392 9.83929L8.30304 6.30316Z"/>
8254
8327
  </svg>`,
8255
8328
 
8256
8329
  "link":
8257
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8330
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8258
8331
  <path d="M12.8885 7.23091L13.9479 6.17155C14.5337 5.58576 14.5337 4.63602 13.9479 4.05023C13.3621 3.46444 12.4124 3.46444 11.8266 4.05023L8.29235 7.58446C7.9263 7.95051 7.90312 8.52994 8.2233 8.92271L8.36141 9.07463C8.68158 9.4674 8.65841 10.0468 8.29235 10.4129C7.90183 10.8034 7.26866 10.8034 6.87814 10.4129C5.70657 9.24131 5.70657 7.34182 6.87814 6.17025L10.4124 2.63602C11.7792 1.26918 13.9953 1.26918 15.3621 2.63602C16.729 4.00285 16.729 6.21893 15.3621 7.58576L14.3028 8.64512C13.9122 9.03564 13.2791 9.03564 12.8885 8.64512C12.498 8.2546 12.498 7.62143 12.8885 7.23091Z"/>
8259
8332
  <path d="M5.11038 10.7664L4.04843 11.8284C3.46264 12.4142 3.46264 13.3639 4.04842 13.9497C4.63421 14.5355 5.58396 14.5355 6.16975 13.9497L9.70657 10.4129C10.0726 10.0468 10.0958 9.46741 9.77563 9.07464L9.63752 8.92272C9.31734 8.52995 9.34052 7.95052 9.70657 7.58446C10.0971 7.19394 10.7303 7.19394 11.1208 7.58446C12.2924 8.75604 12.2924 10.6555 11.1208 11.8271L7.58396 15.3639C6.21712 16.7308 4.00105 16.7308 2.63421 15.3639C1.26738 13.9971 1.26738 11.781 2.63421 10.4142L3.69617 9.35223C4.08669 8.96171 4.71986 8.96171 5.11038 9.35223C5.5009 9.74275 5.5009 10.3759 5.11038 10.7664Z"/>
8260
8333
  </svg>`,
8261
8334
 
8262
8335
  "quote":
8263
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8336
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8264
8337
  <path d="M4.96387 4.23438C6.8769 4.23438 8.42767 5.78522 8.42773 7.69824C8.42773 8.32925 8.25769 8.92015 7.96289 9.42969L7.96387 9.43066L5.11816 14.3584C4.77659 14.95 4.02038 15.153 3.42871 14.8115C2.83701 14.4699 2.63397 13.7128 2.97559 13.1211L4.16113 11.0674C2.63532 10.7052 1.5 9.33485 1.5 7.69824C1.50006 5.78524 3.05086 4.2344 4.96387 4.23438ZM13.0361 4.23438C14.9491 4.23449 16.4999 5.7853 16.5 7.69824C16.5 8.32921 16.3299 8.92017 16.0352 9.42969L16.0361 9.43066L13.1904 14.3584C12.8488 14.9501 12.0917 15.1531 11.5 14.8115C10.9085 14.4698 10.7063 13.7127 11.0479 13.1211L12.2324 11.0674C10.7069 10.7049 9.57227 9.33461 9.57227 7.69824C9.57233 5.78522 11.1231 4.23438 13.0361 4.23438Z"/>
8265
8338
  </svg>`,
8266
8339
 
8267
8340
  "code":
8268
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8341
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8269
8342
  <path d="M6.29289 3.79295C6.68342 3.40243 7.31643 3.40243 7.70696 3.79295C8.09748 4.18348 8.09748 4.81649 7.70696 5.20702L3.91399 8.99999L7.70696 12.793C8.09748 13.1835 8.09748 13.8165 7.70696 14.207C7.31643 14.5975 6.68342 14.5975 6.29289 14.207L1.79289 9.70702C1.40237 9.31649 1.40237 8.68348 1.79289 8.29295L6.29289 3.79295Z"/>
8270
8343
  <path d="M11.707 3.79295C11.3164 3.40243 10.6834 3.40243 10.2929 3.79295C9.90237 4.18348 9.90237 4.81649 10.2929 5.20702L14.0859 8.99999L10.2929 12.793C9.90237 13.1835 9.90237 13.8165 10.2929 14.207C10.6834 14.5975 11.3164 14.5975 11.707 14.207L16.207 9.70702C16.5975 9.31649 16.5975 8.68348 16.207 8.29295L11.707 3.79295Z"/>
8271
8344
  </svg>`,
8272
8345
 
8273
8346
  "ul":
8274
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8347
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8275
8348
  <path d="M3 12.5C3.82843 12.5 4.5 13.1716 4.5 14C4.5 14.8284 3.82843 15.5 3 15.5C2.17157 15.5 1.5 14.8284 1.5 14C1.5 13.1716 2.17157 12.5 3 12.5ZM15.5 13C16.0523 13 16.5 13.4477 16.5 14C16.5 14.5523 16.0523 15 15.5 15H7C6.44772 15 6 14.5523 6 14C6 13.4477 6.44772 13 7 13H15.5ZM3 7.5C3.82843 7.5 4.5 8.17157 4.5 9C4.5 9.82843 3.82843 10.5 3 10.5C2.17157 10.5 1.5 9.82843 1.5 9C1.5 8.17157 2.17157 7.5 3 7.5ZM15.5 8C16.0523 8 16.5 8.44772 16.5 9C16.5 9.55228 16.0523 10 15.5 10H7C6.44772 10 6 9.55228 6 9C6 8.44772 6.44772 8 7 8H15.5ZM3 2.5C3.82843 2.5 4.5 3.17157 4.5 4C4.5 4.82843 3.82843 5.5 3 5.5C2.17157 5.5 1.5 4.82843 1.5 4C1.5 3.17157 2.17157 2.5 3 2.5ZM15.5 3C16.0523 3 16.5 3.44772 16.5 4C16.5 4.55228 16.0523 5 15.5 5H7C6.44772 5 6 4.55228 6 4C6 3.44772 6.44772 3 7 3H15.5Z"/>
8276
8349
  </svg>`,
8277
8350
 
8278
8351
  "ol":
8279
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8352
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8280
8353
  <path d="M15.5 13C16.0523 13 16.5 13.4477 16.5 14C16.5 14.5523 16.0523 15 15.5 15H7C6.44772 15 6 14.5523 6 14C6 13.4477 6.44772 13 7 13H15.5ZM15.5 8C16.0523 8 16.5 8.44772 16.5 9C16.5 9.55228 16.0523 10 15.5 10H7C6.44772 10 6 9.55228 6 9C6 8.44772 6.44772 8 7 8H15.5ZM15.5 3C16.0523 3 16.5 3.44772 16.5 4C16.5 4.55228 16.0523 5 15.5 5H7C6.44772 5 6 4.55228 6 4C6 3.44772 6.44772 3 7 3H15.5Z"/>
8281
8354
  <path d="M2.98657 16.0967C2.68042 16.0967 2.41187 16.0465 2.18091 15.9463C1.95174 15.846 1.77002 15.7046 1.63574 15.522C1.50146 15.3376 1.42448 15.1227 1.40479 14.8774L1.4021 14.8452H2.34204L2.34741 14.8748C2.35815 14.9589 2.39038 15.035 2.44409 15.103C2.49959 15.1711 2.5721 15.2248 2.66162 15.2642C2.75293 15.3035 2.86035 15.3232 2.98389 15.3232C3.10563 15.3232 3.21037 15.3027 3.2981 15.2615C3.38761 15.2185 3.45654 15.1603 3.50488 15.0869C3.55322 15.0135 3.57739 14.9294 3.57739 14.8345V14.8291C3.57739 14.6715 3.51921 14.5516 3.40283 14.4692C3.28646 14.3869 3.12085 14.3457 2.90601 14.3457H2.48706V13.677H2.90063C3.02775 13.677 3.13607 13.6582 3.22559 13.6206C3.31689 13.583 3.38672 13.5302 3.43506 13.4622C3.48519 13.3941 3.51025 13.3153 3.51025 13.2258V13.2205C3.51025 13.1256 3.48877 13.0441 3.4458 12.9761C3.40462 12.9062 3.34375 12.8534 3.26318 12.8176C3.18441 12.78 3.08952 12.7612 2.97852 12.7612C2.86572 12.7612 2.76636 12.7809 2.68042 12.8203C2.59627 12.8579 2.52913 12.9125 2.479 12.9841C2.43066 13.054 2.40112 13.1363 2.39038 13.2312L2.3877 13.2581H1.49341L1.49609 13.2205C1.514 12.977 1.58561 12.7666 1.71094 12.5894C1.83805 12.4103 2.00903 12.2725 2.22388 12.1758C2.44051 12.0773 2.69206 12.0281 2.97852 12.0281C3.27393 12.0281 3.52995 12.0728 3.74658 12.1624C3.96322 12.2501 4.13062 12.3727 4.24878 12.5303C4.36694 12.6878 4.42603 12.8722 4.42603 13.0835V13.0889C4.42603 13.2518 4.38932 13.3941 4.31592 13.5159C4.2443 13.6358 4.14762 13.7343 4.02588 13.8113C3.90592 13.8883 3.77254 13.942 3.62573 13.9724V13.9912C3.91756 14.0199 4.14941 14.1121 4.32129 14.2678C4.49316 14.4236 4.5791 14.6295 4.5791 14.8855V14.8909C4.5791 15.1344 4.51375 15.3474 4.38306 15.53C4.25236 15.7109 4.06795 15.8505 3.82983 15.949C3.59172 16.0474 3.31063 16.0967 2.98657 16.0967Z"/>
8282
8355
  <path d="M1.54443 11V10.342L2.76099 9.20874C2.95076 9.03507 3.09757 8.89274 3.20142 8.78174C3.30705 8.66895 3.37956 8.57316 3.41895 8.49438C3.46012 8.41382 3.48071 8.33415 3.48071 8.25537V8.24463C3.48071 8.14795 3.46012 8.0638 3.41895 7.99219C3.37777 7.92057 3.31779 7.86507 3.23901 7.82568C3.16024 7.7863 3.06714 7.7666 2.95972 7.7666C2.84692 7.7666 2.74756 7.78988 2.66162 7.83643C2.57747 7.88298 2.51123 7.94743 2.46289 8.02979C2.41455 8.11035 2.39038 8.20345 2.39038 8.30908V8.33057L1.48804 8.32788V8.31177C1.48804 8.05396 1.5507 7.82837 1.67603 7.63501C1.80314 7.44165 1.97949 7.29126 2.20508 7.18384C2.43245 7.07463 2.69653 7.02002 2.99731 7.02002C3.28556 7.02002 3.53711 7.06836 3.75195 7.16504C3.96859 7.25993 4.13688 7.39331 4.25684 7.56519C4.37858 7.73706 4.43945 7.93758 4.43945 8.16675V8.18018C4.43945 8.3252 4.40902 8.46932 4.34814 8.61255C4.28727 8.75578 4.18701 8.90885 4.04736 9.07178C3.90771 9.23291 3.71883 9.41642 3.48071 9.62231L2.58374 10.4092L2.85498 9.98486V10.4092L2.58374 10.2319H4.49048V11H1.54443Z"/>
@@ -8284,37 +8357,37 @@ var ToolbarIcons = {
8284
8357
  </svg>`,
8285
8358
 
8286
8359
  "image":
8287
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8360
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8288
8361
  <path d="M14 2C15.6569 2 17 3.34315 17 5V13C17 14.6569 15.6569 16 14 16H4C2.34315 16 1 14.6569 1 13V5C1 3.34315 2.34315 2 4 2H14ZM3.06348 13.3496C3.2053 13.7294 3.57078 14 4 14H13.5859L11 11.4141L9.70703 12.707C9.31651 13.0976 8.68349 13.0976 8.29297 12.707C7.90244 12.3165 7.90244 11.6835 8.29297 11.293L8.58594 11L7 9.41406L3.06348 13.3496ZM4 4C3.44772 4 3 4.44772 3 5V10.5859L6.29297 7.29297L6.36914 7.22461C6.76191 6.90427 7.34092 6.92686 7.70703 7.29297L10 9.58594L10.293 9.29297L10.3691 9.22461C10.7619 8.90427 11.3409 8.92686 11.707 9.29297L15 12.5859V5C15 4.44772 14.5523 4 14 4H4ZM12.5 5C13.3284 5 14 5.67157 14 6.5C14 7.32843 13.3284 8 12.5 8C11.6716 8 11 7.32843 11 6.5C11 5.67157 11.6716 5 12.5 5Z"/>
8289
8362
  </svg>`,
8290
8363
 
8291
8364
  "attachment":
8292
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8365
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8293
8366
  <path d="M13 13.5V6C13 4.067 11.433 2.5 9.5 2.5C7.567 2.5 6 4.067 6 6V13.5C6 14.6046 6.89543 15.5 8 15.5H8.23047C9.20759 15.5 10 14.7076 10 13.7305V7C10 6.72386 9.77614 6.5 9.5 6.5C9.22386 6.5 9 6.72386 9 7V12.5C9 13.0523 8.55228 13.5 8 13.5C7.44772 13.5 7 13.0523 7 12.5V7C7 5.61929 8.11929 4.5 9.5 4.5C10.8807 4.5 12 5.61929 12 7V13.7305C12 15.8122 10.3122 17.5 8.23047 17.5H8C5.79086 17.5 4 15.7091 4 13.5V6C4 2.96243 6.46243 0.5 9.5 0.5C12.5376 0.5 15 2.96243 15 6V13.5C15 14.0523 14.5523 14.5 14 14.5C13.4477 14.5 13 14.0523 13 13.5Z"/>
8294
8367
  </svg>`,
8295
8368
 
8296
8369
  "table":
8297
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8370
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8298
8371
  <path d="M15 1C16.1046 1 17 1.89543 17 3V15C17 16.1046 16.1046 17 15 17H3C1.89543 17 1 16.1046 1 15V3C1 1.89543 1.89543 1 3 1H15ZM3 15H8V10H3V15ZM10 10V15H15V10H10ZM10 8H15V3H10V8ZM3 8H8V3H3V8Z"/>
8299
8372
  </svg>`,
8300
8373
 
8301
8374
  "hr":
8302
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8375
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8303
8376
  <path d="M12.75 12C13.1642 12 13.5 12.3358 13.5 12.75V14.25C13.5 14.6642 13.1642 15 12.75 15H5.25C4.83579 15 4.5 14.6642 4.5 14.25V12.75C4.5 12.3358 4.83579 12 5.25 12H12.75ZM15.4863 8C16.0461 8 16.5 8.44771 16.5 9C16.5 9.55229 16.0461 10 15.4863 10H2.51367C1.95392 10 1.5 9.55229 1.5 9C1.5 8.44771 1.95392 8 2.51367 8H15.4863ZM12.75 3C13.1642 3 13.5 3.33579 13.5 3.75V5.25C13.5 5.66421 13.1642 6 12.75 6H5.25C4.83579 6 4.5 5.66421 4.5 5.25V3.75C4.5 3.33579 4.83579 3 5.25 3H12.75Z"/>
8304
8377
  </svg>`,
8305
8378
 
8306
8379
  "undo":
8307
- `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
8380
+ `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8308
8381
  <path d="M8.36612 5.36612C8.85427 4.87796 9.64554 4.87796 10.1337 5.36612C10.6218 5.85428 10.6218 6.64557 10.1337 7.13369L7.26748 9.9999H15.2499C18.1494 9.99996 20.4999 12.3504 20.4999 15.2499V19.2499C20.4999 19.9402 19.9402 20.4999 19.2499 20.4999C18.5596 20.4999 18 19.9402 17.9999 19.2499V15.2499C17.9999 13.7312 16.7686 12.5 15.2499 12.4999H7.26748L10.1337 15.3661C10.6218 15.8543 10.6218 16.6456 10.1337 17.1337C9.64557 17.6218 8.85428 17.6218 8.36612 17.1337L3.36612 12.1337C2.87796 11.6455 2.87796 10.8543 3.36612 10.3661L8.36612 5.36612Z"/>
8309
8382
  </svg>`,
8310
8383
 
8311
8384
  "redo":
8312
- `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
8385
+ `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8313
8386
  <path d="M15.6338 5.1163C15.1456 4.62814 14.3543 4.62814 13.8662 5.1163C13.3781 5.60446 13.3781 6.39575 13.8662 6.88388L16.7324 9.75009H8.74997C5.85052 9.75014 3.49997 12.1006 3.49997 15.0001V19.0001C3.50002 19.6904 4.05969 20.25 4.74997 20.2501C5.4403 20.2501 5.99992 19.6904 5.99997 19.0001V15.0001C5.99997 13.4813 7.23123 12.2501 8.74997 12.2501H16.7324L13.8662 15.1163C13.3781 15.6045 13.3781 16.3958 13.8662 16.8839C14.3543 17.372 15.1456 17.3719 15.6338 16.8839L20.6338 11.8839C21.1219 11.3957 21.1219 10.6045 20.6338 10.1163L15.6338 5.1163Z" />
8314
8387
  </svg>`,
8315
8388
 
8316
8389
  "overflow":
8317
- `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
8390
+ `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
8318
8391
  <path d="M3 6.75C4.24264 6.75 5.25 7.75736 5.25 9C5.25 10.2426 4.24264 11.25 3 11.25C1.75736 11.25 0.75 10.2426 0.75 9C0.75 7.75736 1.75736 6.75 3 6.75ZM9 6.75C10.2426 6.75 11.25 7.75736 11.25 9C11.25 10.2426 10.2426 11.25 9 11.25C7.75736 11.25 6.75 10.2426 6.75 9C6.75 7.75736 7.75736 6.75 9 6.75ZM15 6.75C16.2426 6.75 17.25 7.75736 17.25 9C17.25 10.2426 16.2426 11.25 15 11.25C13.7574 11.25 12.75 10.2426 12.75 9C12.75 7.75736 13.7574 6.75 15 6.75Z"/>
8319
8392
  </svg>`
8320
8393
  };
@@ -8441,14 +8514,21 @@ class LexicalToolbarElement extends HTMLElement {
8441
8514
  }
8442
8515
  }
8443
8516
 
8444
- #dispatchButtonCommand(event, { dataset: { command, payload } }) {
8445
- const isKeyboard = event instanceof PointerEvent && event.pointerId === -1;
8517
+ #dispatchButtonCommand(event, button) {
8518
+ if (button.ariaDisabled === "true") return
8519
+
8520
+ const { command, payload } = button.dataset;
8521
+ const shouldKeepToolbarFocus = isKeyboardActivation(event) && !this.#belongsToDropdown(button);
8446
8522
 
8447
8523
  this.editor.update(() => {
8448
8524
  this.editor.dispatchCommand(command, payload);
8449
- }, { tag: isKeyboard ? qn : undefined });
8525
+ }, { tag: shouldKeepToolbarFocus ? qn : undefined });
8526
+
8527
+ if (!shouldKeepToolbarFocus) this.editor.focus();
8528
+ }
8450
8529
 
8451
- if (!isKeyboard) this.editor.focus();
8530
+ #belongsToDropdown(button) {
8531
+ return button.closest("[data-dropdown-panel]") != null
8452
8532
  }
8453
8533
 
8454
8534
  #bindHotkeys() {
@@ -8488,8 +8568,8 @@ class LexicalToolbarElement extends HTMLElement {
8488
8568
  }
8489
8569
 
8490
8570
  #handleEditorFocus = () => {
8491
- const firstVisible = this.#buttons.find(isActiveAndVisible);
8492
- if (firstVisible) firstVisible.tabIndex = 0;
8571
+ const firstVisibleButton = this.#toolbarButtons.find(isActiveAndVisible);
8572
+ if (firstVisibleButton) firstVisibleButton.tabIndex = 0;
8493
8573
  }
8494
8574
 
8495
8575
  #handleEditorBlur = () => {
@@ -8497,11 +8577,11 @@ class LexicalToolbarElement extends HTMLElement {
8497
8577
  }
8498
8578
 
8499
8579
  #handleKeydown = (event) => {
8500
- handleRollingTabIndex(this.#buttons, event);
8580
+ handleRollingTabIndex(this.#toolbarButtons, event);
8501
8581
  }
8502
8582
 
8503
8583
  #resetTabIndexValues() {
8504
- this.#buttons.forEach((button) => {
8584
+ this.#toolbarButtons.forEach((button) => {
8505
8585
  button.tabIndex = -1;
8506
8586
  });
8507
8587
  }
@@ -8538,7 +8618,7 @@ class LexicalToolbarElement extends HTMLElement {
8538
8618
  this.#setButtonPressed("underline", isUnderline);
8539
8619
 
8540
8620
  this.#setButtonPressed("format", isInHeading);
8541
- this.#setButtonPressed("paragraph", !isInHeading);
8621
+ this.#setButtonChecked("paragraph", !isInHeading);
8542
8622
 
8543
8623
  this.querySelector("lexxy-heading-dropdown")
8544
8624
  ?.updateActiveHeading(headingTag);
@@ -8557,25 +8637,17 @@ class LexicalToolbarElement extends HTMLElement {
8557
8637
 
8558
8638
  #setButtonPressed(name, isPressed) {
8559
8639
  const button = this.querySelector(`[name="${name}"]`);
8560
- if (button) {
8561
- const next = isPressed.toString();
8562
- if (button.getAttribute("aria-pressed") !== next) {
8563
- button.setAttribute("aria-pressed", next);
8564
- }
8565
- }
8640
+ if (button) button.ariaPressed = isPressed;
8641
+ }
8642
+
8643
+ #setButtonChecked(name, isChecked) {
8644
+ const button = this.querySelector(`[name="${name}"]`);
8645
+ if (button) button.ariaChecked = isChecked;
8566
8646
  }
8567
8647
 
8568
8648
  #setButtonDisabled(name, isDisabled) {
8569
8649
  const button = this.querySelector(`[name="${name}"]`);
8570
- if (button) {
8571
- if (button.disabled !== isDisabled) {
8572
- button.disabled = isDisabled;
8573
- }
8574
- const next = isDisabled.toString();
8575
- if (button.getAttribute("aria-disabled") !== next) {
8576
- button.setAttribute("aria-disabled", next);
8577
- }
8578
- }
8650
+ if (button) button.ariaDisabled = isDisabled;
8579
8651
  }
8580
8652
 
8581
8653
  #refreshOverflow() {
@@ -8676,8 +8748,10 @@ class LexicalToolbarElement extends HTMLElement {
8676
8748
  return Array.from(this.querySelectorAll(":scope > button:not([data-prevent-overflow])"))
8677
8749
  }
8678
8750
 
8679
- get #buttons() {
8680
- return Array.from(this.querySelectorAll(":scope button"))
8751
+ get #toolbarButtons() {
8752
+ return Array.from(this.querySelectorAll(":scope button")).filter((button) => {
8753
+ return !button.closest("[data-dropdown-panel]")
8754
+ })
8681
8755
  }
8682
8756
 
8683
8757
  get #toolbarItems() {
@@ -8716,8 +8790,8 @@ class LexicalToolbarElement extends HTMLElement {
8716
8790
  <button data-dropdown-trigger class="lexxy-editor__toolbar-button lexxy-editor__toolbar-button--chevron" type="button" name="format" title="Text formatting" aria-haspopup="menu" aria-expanded="false">
8717
8791
  ${ToolbarIcons.heading}
8718
8792
  </button>
8719
- <div data-dropdown-panel role="menu" class="lexxy-editor__toolbar-dropdown-list" hidden>
8720
- <button type="button" name="paragraph" data-command="setFormatParagraph" title="Paragraph" role="menuitem">
8793
+ <div data-dropdown-panel role="menu" aria-label="Text formatting" class="lexxy-editor__toolbar-dropdown-list" hidden>
8794
+ <button type="button" name="paragraph" data-command="setFormatParagraph" title="Paragraph" role="menuitemradio">
8721
8795
  ${ToolbarIcons.paragraph} <span>Normal</span>
8722
8796
  </button>
8723
8797
  <lexxy-heading-dropdown>
@@ -8734,7 +8808,7 @@ class LexicalToolbarElement extends HTMLElement {
8734
8808
  <button data-dropdown-trigger class="lexxy-editor__toolbar-button lexxy-editor__toolbar-button--chevron" type="button" name="highlight" title="Color highlight" aria-haspopup="menu" aria-expanded="false">
8735
8809
  ${ToolbarIcons.highlight}
8736
8810
  </button>
8737
- <div data-dropdown-panel role="menu" hidden>
8811
+ <div data-dropdown-panel role="menu" aria-label="Color highlight" hidden>
8738
8812
  <div class="lexxy-highlight-colors"></div>
8739
8813
  <button data-command="removeHighlight" type="button" class="lexxy-editor__toolbar-button lexxy-editor__toolbar-dropdown-reset" role="menuitem">Remove all coloring</button>
8740
8814
  </div>
@@ -8776,19 +8850,19 @@ class LexicalToolbarElement extends HTMLElement {
8776
8850
  ${ToolbarIcons.hr}
8777
8851
  </button>
8778
8852
 
8779
- <button class="lexxy-editor__toolbar-button lexxy-editor__toolbar-button--push-right" type="button" name="undo" data-command="undo" title="Undo" disabled aria-disabled="true">
8853
+ <button class="lexxy-editor__toolbar-button lexxy-editor__toolbar-button--push-right" type="button" name="undo" data-command="undo" title="Undo" aria-disabled="true">
8780
8854
  ${ToolbarIcons.undo}
8781
8855
  </button>
8782
8856
 
8783
- <button class="lexxy-editor__toolbar-button" type="button" name="redo" data-command="redo" title="Redo" disabled aria-disabled="true">
8857
+ <button class="lexxy-editor__toolbar-button" type="button" name="redo" data-command="redo" title="Redo" aria-disabled="true">
8784
8858
  ${ToolbarIcons.redo}
8785
8859
  </button>
8786
8860
 
8787
8861
  <lexxy-toolbar-dropdown class="lexxy-editor__toolbar-dropdown lexxy-editor__toolbar-button--push-right lexxy-editor__toolbar-overflow">
8788
- <button data-dropdown-trigger class="lexxy-editor__toolbar-button" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="Show more toolbar buttons">
8862
+ <button data-dropdown-trigger class="lexxy-editor__toolbar-button" type="button" title="More options" aria-haspopup="menu" aria-expanded="false">
8789
8863
  ${ToolbarIcons.overflow}
8790
8864
  </button>
8791
- <div data-dropdown-panel role="menu" class="lexxy-editor__toolbar-overflow-menu" aria-label="More toolbar buttons" hidden></div>
8865
+ <div data-dropdown-panel role="menu" class="lexxy-editor__toolbar-overflow-menu" aria-label="More options" hidden></div>
8792
8866
  </lexxy-toolbar-dropdown>
8793
8867
  `
8794
8868
  }
@@ -8832,9 +8906,10 @@ function nextFrame() {
8832
8906
 
8833
8907
  class ToolbarDropdown extends HTMLElement {
8834
8908
  #listeners = new ListenerBin()
8909
+ #shouldReturnFocusToTrigger = false
8835
8910
 
8836
8911
  connectedCallback() {
8837
- this.#onToolbarEditor(() => {
8912
+ this.#onHostEditor(() => {
8838
8913
  this.#registerListeners();
8839
8914
  this.editorReady();
8840
8915
  });
@@ -8856,16 +8931,16 @@ class ToolbarDropdown extends HTMLElement {
8856
8931
  return this.querySelector(":scope > [data-dropdown-panel]")
8857
8932
  }
8858
8933
 
8859
- get toolbar() {
8860
- return this.closest("lexxy-toolbar")
8934
+ get host() {
8935
+ return this.closest("lexxy-toolbar, lexxy-table-tools")
8861
8936
  }
8862
8937
 
8863
8938
  get editorElement() {
8864
- return this.toolbar?.editorElement
8939
+ return this.host?.editorElement
8865
8940
  }
8866
8941
 
8867
8942
  get editor() {
8868
- return this.toolbar?.editor
8943
+ return this.host?.editor
8869
8944
  }
8870
8945
 
8871
8946
  get isOpen() {
@@ -8882,7 +8957,7 @@ class ToolbarDropdown extends HTMLElement {
8882
8957
 
8883
8958
  open() {
8884
8959
  if (this.isOpen) return
8885
- this.trigger.setAttribute("aria-expanded", "true");
8960
+ this.trigger.ariaExpanded = true;
8886
8961
  this.panel.hidden = false;
8887
8962
  this.onOpen();
8888
8963
  this.#focusFirstInteractive();
@@ -8892,7 +8967,7 @@ class ToolbarDropdown extends HTMLElement {
8892
8967
  if (focusEditor) this.editor?.focus();
8893
8968
 
8894
8969
  if (this.isClosed) return
8895
- this.trigger.setAttribute("aria-expanded", "false");
8970
+ this.trigger.ariaExpanded = false;
8896
8971
  this.panel.hidden = true;
8897
8972
  this.onClose();
8898
8973
  }
@@ -8904,32 +8979,49 @@ class ToolbarDropdown extends HTMLElement {
8904
8979
  );
8905
8980
  }
8906
8981
 
8907
- #handleTriggerClick = () => {
8982
+ #handleTriggerClick = (event) => {
8908
8983
  if (this.isOpen) {
8909
8984
  this.close({ focusEditor: false });
8910
8985
  } else {
8911
- this.toolbar?.closeDropdowns({ except: this });
8986
+ this.#shouldReturnFocusToTrigger = this.#isOpenedFromHost(event);
8987
+ this.host?.closeDropdowns({ except: this });
8912
8988
  this.open();
8913
8989
  }
8914
8990
  }
8915
8991
 
8916
- async #onToolbarEditor(callback) {
8917
- if (!this.toolbar) return
8992
+ #isOpenedFromHost(event) {
8993
+ return isKeyboardActivation(event) && this.host?.contains(document.activeElement)
8994
+ }
8995
+
8996
+ async #onHostEditor(callback) {
8997
+ if (!this.host) return
8918
8998
 
8919
- await this.toolbar.getEditorElement();
8920
- if (this.isConnected && this.toolbar) callback();
8999
+ await this.host.getEditorElement();
9000
+ if (this.isConnected && this.host) callback();
8921
9001
  }
8922
9002
 
8923
9003
  #handleKeyDown = (event) => {
8924
- if (event.key === "Escape") {
9004
+ if (event.key === "Escape" && this.isOpen) {
9005
+ event.stopPropagation();
9006
+ this.close({ focusEditor: !this.#shouldReturnFocusToTrigger });
9007
+ if (this.#shouldReturnFocusToTrigger) this.trigger?.focus();
9008
+ } else if (this.isOpen && this.panel.role === "dialog") {
9009
+ trapFocusAtTabBoundary(this.panel, event);
9010
+ } else if (this.#isNavigatingMenu(event)) {
8925
9011
  event.stopPropagation();
8926
- this.close();
9012
+ handleRollingTabIndex(this.#buttons, event, { orientation: "both", wrap: true });
8927
9013
  }
8928
9014
  }
8929
9015
 
9016
+ #isNavigatingMenu(event) {
9017
+ return this.panel.role === "menu" && this.panel.contains(event.target)
9018
+ }
9019
+
8930
9020
  async #focusFirstInteractive() {
8931
- this.#interactiveElements[0]?.focus();
8932
- await this.#resetTabIndexValues();
9021
+ // Ask for the ring explicitly: opening the menu with the mouse otherwise leaves the
9022
+ // first item focused without a focus ring, since focus() inherits the mouse modality.
9023
+ this.#interactiveElements[0]?.focus({ focusVisible: true });
9024
+ if (this.panel.role === "menu") await this.#resetTabIndexValues();
8933
9025
  }
8934
9026
 
8935
9027
  async #resetTabIndexValues() {
@@ -9011,8 +9103,8 @@ class HeadingDropdown extends HTMLElement {
9011
9103
  updateActiveHeading(tag) {
9012
9104
  this.#headingButtons.forEach(button => {
9013
9105
  const next = (button.dataset.heading === tag).toString();
9014
- if (button.getAttribute("aria-pressed") !== next) {
9015
- button.setAttribute("aria-pressed", next);
9106
+ if (button.getAttribute("aria-checked") !== next) {
9107
+ button.setAttribute("aria-checked", next);
9016
9108
  }
9017
9109
  });
9018
9110
  }
@@ -9057,7 +9149,7 @@ class HeadingDropdown extends HTMLElement {
9057
9149
  button.classList.add("lexxy-heading-button");
9058
9150
  button.name = name;
9059
9151
  button.title = label;
9060
- button.setAttribute("role", "menuitem");
9152
+ button.setAttribute("role", "menuitemradio");
9061
9153
  button.innerHTML = `${icon} <span>${label}</span>`;
9062
9154
  return button
9063
9155
  }
@@ -9092,6 +9184,143 @@ class HeadingDropdown extends HTMLElement {
9092
9184
  }
9093
9185
  }
9094
9186
 
9187
+ // Shared, strictly-contained element used to attach ephemeral nodes when we
9188
+ // need to read computed styles (e.g. canonicalizing style values, resolving
9189
+ // CSS custom properties). The container is created once and attached to
9190
+ // `document.body` once; subsequent child mutations happen *inside* the
9191
+ // contained subtree so they do not invalidate style on the rest of the page.
9192
+ //
9193
+ // Without this, `document.body.appendChild(...)` / `element.remove()` calls
9194
+ // forced the browser to re-evaluate every ancestor-dependent selector (`:has()`,
9195
+ // descendant combinators, universal sibling rules) across the document on each
9196
+ // invocation — a 13,000+ element style recalc per call on a typical Basecamp
9197
+ // page.
9198
+
9199
+ let resolverRoot = null;
9200
+
9201
+ function styleResolverRoot() {
9202
+ if (resolverRoot && resolverRoot.isConnected) return resolverRoot
9203
+
9204
+ resolverRoot = document.createElement("div");
9205
+ resolverRoot.setAttribute("aria-hidden", "true");
9206
+ resolverRoot.setAttribute("data-lexxy-style-resolver", "");
9207
+ // `contain: strict` (size, layout, paint, style) isolates everything.
9208
+ // The root itself paints nothing (visibility hidden), has zero
9209
+ // geometric impact (position fixed, intrinsic size via contain), and
9210
+ // never leaks style invalidation to its ancestors.
9211
+ resolverRoot.style.cssText = "contain: strict; position: fixed; top: 0; left: 0; visibility: hidden; pointer-events: none; width: 0; height: 0;";
9212
+ document.body.appendChild(resolverRoot);
9213
+ return resolverRoot
9214
+ }
9215
+
9216
+ function isSelectionHighlighted(selection) {
9217
+ if (!Fr(selection)) return false
9218
+
9219
+ if (selection.isCollapsed()) {
9220
+ return hasHighlightStyles(selection.style)
9221
+ } else {
9222
+ return selection.hasFormat("highlight")
9223
+ }
9224
+ }
9225
+
9226
+ function getHighlightStyles(selection) {
9227
+ if (!Fr(selection)) return null
9228
+
9229
+ let styles = oe$5(selection.style);
9230
+ if (!styles.color && !styles["background-color"]) {
9231
+ const anchorNode = selection.anchor.getNode();
9232
+ if (Tr(anchorNode)) {
9233
+ styles = oe$5(anchorNode.getStyle());
9234
+ }
9235
+ }
9236
+
9237
+ const color = styles.color || null;
9238
+ const backgroundColor = styles["background-color"] || null;
9239
+ if (!color && !backgroundColor) return null
9240
+
9241
+ return { color, backgroundColor }
9242
+ }
9243
+
9244
+ function hasHighlightStyles(cssOrStyles) {
9245
+ const styles = typeof cssOrStyles === "string" ? oe$5(cssOrStyles) : cssOrStyles;
9246
+ return !!(styles.color || styles["background-color"])
9247
+ }
9248
+
9249
+ function normalizeColorButtons(buttons) {
9250
+ return buttons.map((button) => (typeof button === "string" ? { value: button, label: button } : button))
9251
+ }
9252
+
9253
+ function applyCanonicalizers(styles, canonicalizers = []) {
9254
+ return canonicalizers.reduce((css, canonicalizer) => {
9255
+ return canonicalizer.applyCanonicalization(css)
9256
+ }, styles)
9257
+ }
9258
+
9259
+ class StyleCanonicalizer {
9260
+ constructor(property, allowedValues= []) {
9261
+ this._property = property;
9262
+ this._allowedValues = allowedValues;
9263
+ this._canonicalValues = this.#allowedValuesIdentityObject;
9264
+ }
9265
+
9266
+ applyCanonicalization(css) {
9267
+ const styles = { ...oe$5(css) };
9268
+
9269
+ styles[this._property] = this.getCanonicalAllowedValue(styles[this._property]);
9270
+ if (!styles[this._property]) {
9271
+ delete styles[this._property];
9272
+ }
9273
+
9274
+ return F$6(styles)
9275
+ }
9276
+
9277
+ getCanonicalAllowedValue(value) {
9278
+ return this._canonicalValues[value] ||= this.#resolveCannonicalValue(value)
9279
+ }
9280
+
9281
+ // Private
9282
+
9283
+ get #allowedValuesIdentityObject() {
9284
+ return this._allowedValues.reduce((object, value) => ({ ...object, [value]: value }), {})
9285
+ }
9286
+
9287
+ #resolveCannonicalValue(value) {
9288
+ let index = this.#computedAllowedValues.indexOf(value);
9289
+ if (index === -1) {
9290
+ index = this.#computedAllowedValues.indexOf(computeStyleValues(this._property, [ value ])[0]);
9291
+ }
9292
+ return index === -1 ? null : this._allowedValues[index]
9293
+ }
9294
+
9295
+ get #computedAllowedValues() {
9296
+ return this._computedAllowedValues ||= computeStyleValues(this._property, this._allowedValues)
9297
+ }
9298
+ }
9299
+
9300
+ // Separates DOM writes from layout reads to avoid forced reflows, and attaches
9301
+ // resolver elements to a strictly-contained root (outside the normal document
9302
+ // flow) so neither the attach nor the detach invalidate styles on the rest of
9303
+ // the page. Without containment, appending to `document.body` triggered a
9304
+ // page-wide style recalc on every canonicalization pass.
9305
+ function computeStyleValues(property, values) {
9306
+ const fragment = document.createDocumentFragment();
9307
+
9308
+ const elements = values.map(value => {
9309
+ const element = createElement("span", { style: `display: none; ${property}: ${value};` });
9310
+ fragment.appendChild(element);
9311
+ return element
9312
+ });
9313
+
9314
+ styleResolverRoot().appendChild(fragment);
9315
+
9316
+ const computed = elements.map(element =>
9317
+ window.getComputedStyle(element).getPropertyValue(property)
9318
+ );
9319
+
9320
+ elements.forEach(element => element.remove());
9321
+ return computed
9322
+ }
9323
+
9095
9324
  const APPLY_HIGHLIGHT_SELECTOR = "button.lexxy-highlight-button";
9096
9325
  const REMOVE_HIGHLIGHT_SELECTOR = "[data-command='removeHighlight']";
9097
9326
 
@@ -9123,27 +9352,36 @@ class HighlightDropdown extends ToolbarDropdown {
9123
9352
 
9124
9353
  const colorGroups = this.editorElement.config.get("highlight.buttons");
9125
9354
 
9126
- this.#populateButtonGroup("color", colorGroups.color);
9127
- this.#populateButtonGroup("background-color", colorGroups["background-color"]);
9355
+ this.#appendColorGroup("Text color", "color", colorGroups.color);
9356
+ this.#appendColorGroup("Background color", "background-color", colorGroups["background-color"]);
9128
9357
 
9129
9358
  const maxNumberOfColors = Math.max(colorGroups.color.length, colorGroups["background-color"].length);
9130
9359
  this.panel.style.setProperty("--max-colors", maxNumberOfColors);
9131
9360
  }
9132
9361
 
9133
- #populateButtonGroup(attribute, values) {
9134
- values.forEach((value, index) => {
9135
- this.#buttonContainer.appendChild(this.#createButton(attribute, value, index));
9362
+ #appendColorGroup(label, attribute, buttons) {
9363
+ const group = createElement("div", {
9364
+ role: "group",
9365
+ class: "lexxy-highlight-colors__group",
9366
+ "aria-label": label
9367
+ });
9368
+
9369
+ normalizeColorButtons(buttons).forEach((button, index) => {
9370
+ group.appendChild(this.#createButton(attribute, button, index));
9136
9371
  });
9372
+
9373
+ this.#buttonContainer.append(group);
9137
9374
  }
9138
9375
 
9139
- #createButton(attribute, value, index) {
9376
+ #createButton(attribute, button, index) {
9140
9377
  return createElement("button", {
9141
9378
  type: "button",
9142
- dataset: { value, style: attribute },
9143
- style: `${attribute}: ${value}`,
9379
+ dataset: { value: button.value, style: attribute },
9380
+ style: `${attribute}: ${button.value}`,
9144
9381
  class: "lexxy-editor__toolbar-button lexxy-highlight-button",
9145
9382
  name: `${attribute}-${index}`,
9146
- role: "menuitem"
9383
+ role: "menuitemcheckbox",
9384
+ "aria-label": button.label
9147
9385
  })
9148
9386
  }
9149
9387
 
@@ -9167,11 +9405,7 @@ class HighlightDropdown extends ToolbarDropdown {
9167
9405
  const backgroundColor = ne$4(selection, "background-color", NO_STYLE);
9168
9406
 
9169
9407
  this.#colorButtons.forEach(button => {
9170
- const matchesSelection = button.dataset.value === textColor || button.dataset.value === backgroundColor;
9171
- const next = matchesSelection.toString();
9172
- if (button.getAttribute("aria-pressed") !== next) {
9173
- button.setAttribute("aria-pressed", next);
9174
- }
9408
+ button.ariaChecked = button.dataset.value === textColor || button.dataset.value === backgroundColor;
9175
9409
  });
9176
9410
 
9177
9411
  const hasHighlight = textColor !== NO_STYLE || backgroundColor !== NO_STYLE;
@@ -9558,13 +9792,35 @@ class CustomActionTextAttachmentNode extends Ji {
9558
9792
  // is cosmetic: it is a nested attachment's rendering inside this one, not the
9559
9793
  // attribute anything re-imports from.
9560
9794
  figure.insertAdjacentHTML("beforeend", EditorSanitizer.for(editor).sanitize(this.innerHtml, { safeForXml: true }));
9561
-
9562
- const deleteButton = createElement("lexxy-node-delete-button");
9563
- figure.appendChild(deleteButton);
9795
+ this.#markImagesAsDecorative(figure);
9796
+ this.#tagLabelImage(figure);
9797
+ this.#tagLabelMirrors(figure);
9564
9798
 
9565
9799
  return figure
9566
9800
  }
9567
9801
 
9802
+ exposeLabel(figure) {
9803
+ const labelImage = figure.querySelector("[data-lexxy-label-image]");
9804
+ if (labelImage) labelImage.alt = this.label;
9805
+
9806
+ for (const span of figure.querySelectorAll("[data-lexxy-label-mirror]")) {
9807
+ span.setAttribute("aria-hidden", "true");
9808
+ }
9809
+ }
9810
+
9811
+ get label() {
9812
+ return this.getReadableTextContent()
9813
+ }
9814
+
9815
+ restoreLabel(figure) {
9816
+ const labelImage = figure.querySelector("[data-lexxy-label-image]");
9817
+ if (labelImage) labelImage.alt = labelImage.dataset.lexxyOriginalAlt;
9818
+
9819
+ for (const span of figure.querySelectorAll("[data-lexxy-label-mirror]")) {
9820
+ span.removeAttribute("aria-hidden");
9821
+ }
9822
+ }
9823
+
9568
9824
  updateDOM() {
9569
9825
  return false
9570
9826
  }
@@ -9605,6 +9861,55 @@ class CustomActionTextAttachmentNode extends Ji {
9605
9861
  decorate() {
9606
9862
  return null
9607
9863
  }
9864
+
9865
+ #markImagesAsDecorative(figure) {
9866
+ for (const img of figure.querySelectorAll("img:not([alt])")) {
9867
+ img.alt = "";
9868
+ }
9869
+ }
9870
+
9871
+ // Images injected later by other modules must not become the announcement image.
9872
+ #tagLabelImage(figure) {
9873
+ const image = figure.querySelector("img");
9874
+ if (image) {
9875
+ image.setAttribute("data-lexxy-label-image", "");
9876
+ image.dataset.lexxyOriginalAlt = image.alt;
9877
+ }
9878
+ }
9879
+
9880
+ // Duplicate labels would be spoken twice. Only authored spans should be silenced,
9881
+ // since the fake selection injects its own label later.
9882
+ #tagLabelMirrors(figure) {
9883
+ const trimmedLabel = this.label.trim();
9884
+ const matches = [ ...figure.querySelectorAll("span") ].filter((span) => span.textContent.trim() === trimmedLabel);
9885
+ const deepest = matches.filter((span) => !matches.some((other) => other !== span && span.contains(other)));
9886
+ const labelImage = figure.querySelector("[data-lexxy-label-image]");
9887
+
9888
+ for (const span of deepest) {
9889
+ if (span.getAttribute("aria-hidden") !== "true") {
9890
+ if (span.contains(labelImage)) {
9891
+ this.#wrapLabelTextNodesIn(span);
9892
+ } else {
9893
+ span.setAttribute("data-lexxy-label-mirror", "");
9894
+ }
9895
+ }
9896
+ }
9897
+ }
9898
+
9899
+ #wrapLabelTextNodesIn(element) {
9900
+ const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
9901
+ const textNodes = [];
9902
+
9903
+ while (walker.nextNode()) {
9904
+ if (walker.currentNode.textContent.trim()) textNodes.push(walker.currentNode);
9905
+ }
9906
+
9907
+ for (const textNode of textNodes) {
9908
+ const mirror = createElement("span", { "data-lexxy-label-mirror": "" });
9909
+ textNode.replaceWith(mirror);
9910
+ mirror.append(textNode);
9911
+ }
9912
+ }
9608
9913
  }
9609
9914
 
9610
9915
  function $isCustomActionTextAttachmentNode(node) {
@@ -9718,16 +10023,45 @@ function $createNodeSelectionWith(...nodes) {
9718
10023
  return selection
9719
10024
  }
9720
10025
 
9721
- function $isShadowRoot(node) {
9722
- return Wi(node) && Is(node) && !Vi(node)
10026
+ function $singleSelectedNode() {
10027
+ const selection = Qr();
10028
+ if (Ir(selection)) {
10029
+ const nodes = selection.getNodes();
10030
+ if (nodes.length === 1) {
10031
+ return nodes[0]
10032
+ } else {
10033
+ return null
10034
+ }
10035
+ } else {
10036
+ return null
10037
+ }
9723
10038
  }
9724
10039
 
9725
- function $isSafeForRoot(node) {
9726
- return (Wi(node) || ji(node)) && !node.isParentRequired()
10040
+ function $selectedLabelledDecoratorNode() {
10041
+ const node = $singleSelectedNode();
10042
+ if (typeof node?.label === "string") {
10043
+ return { key: node.getKey(), label: node.label }
10044
+ } else {
10045
+ return null
10046
+ }
9727
10047
  }
9728
10048
 
9729
- function $makeSafeForRoot(node) {
9730
- if ($isSafeForRoot(node)) {
10049
+ function registerLabelledDecoratorSelection(editor, onChange) {
10050
+ return editor.registerUpdateListener(({ editorState }) => {
10051
+ onChange(editorState.read($selectedLabelledDecoratorNode));
10052
+ })
10053
+ }
10054
+
10055
+ function $isShadowRoot(node) {
10056
+ return Wi(node) && Is(node) && !Vi(node)
10057
+ }
10058
+
10059
+ function $isSafeForRoot(node) {
10060
+ return (Wi(node) || ji(node)) && !node.isParentRequired()
10061
+ }
10062
+
10063
+ function $makeSafeForRoot(node) {
10064
+ if ($isSafeForRoot(node)) {
9731
10065
  return node
9732
10066
  } else if (node.getParent()) {
9733
10067
  return Tt$4(node, () => node.createParentElementNode())
@@ -9743,6 +10077,10 @@ function getListType(node) {
9743
10077
  return list?.getListType() ?? null
9744
10078
  }
9745
10079
 
10080
+ function announceFromEditor(editor, message) {
10081
+ editor.getRootElement()?.closest("lexxy-editor")?.announce(message);
10082
+ }
10083
+
9746
10084
  function isEditorFocused(editor) {
9747
10085
  const rootElement = editor.getRootElement();
9748
10086
  return rootElement !== null && rootElement.contains(document.activeElement)
@@ -10318,7 +10656,7 @@ class ActionTextAttachmentNode extends Ji {
10318
10656
  node: new ActionTextAttachmentNode({
10319
10657
  src: img.getAttribute("src"),
10320
10658
  fileName: fileName,
10321
- caption: img.getAttribute("alt") || "",
10659
+ altText: img.getAttribute("alt"),
10322
10660
  contentType: "image/*",
10323
10661
  width: img.getAttribute("width"),
10324
10662
  height: img.getAttribute("height")
@@ -10395,14 +10733,27 @@ class ActionTextAttachmentNode extends Ji {
10395
10733
  updateDOM(prevNode, dom) {
10396
10734
  if (this.uploadError !== prevNode.uploadError) return true
10397
10735
 
10398
- const caption = dom.querySelector("figcaption textarea");
10399
- if (caption && this.caption) {
10400
- caption.value = this.caption;
10736
+ const image = dom.querySelector("img");
10737
+ if (image && prevNode.altText !== this.altText) {
10738
+ image.alt = this.altText;
10739
+ }
10740
+
10741
+ if (prevNode.caption !== this.caption) {
10742
+ dom.querySelector("figcaption")?.toggleAttribute("data-placeholder", !this.caption);
10743
+ }
10744
+
10745
+ const captionText = dom.querySelector("figcaption .attachment__caption-text");
10746
+ if (captionText && prevNode.captionLabel !== this.captionLabel) {
10747
+ captionText.textContent = this.captionLabel;
10401
10748
  }
10402
10749
 
10403
10750
  return false
10404
10751
  }
10405
10752
 
10753
+ get captionLabel() {
10754
+ return this.caption || this.fileName || ""
10755
+ }
10756
+
10406
10757
  getTextContent() {
10407
10758
  return `[${this.caption || this.fileName}]\n\n`
10408
10759
  }
@@ -10464,9 +10815,6 @@ class ActionTextAttachmentNode extends Ji {
10464
10815
  figure.draggable = true;
10465
10816
  figure.dataset.lexicalNodeKey = this.__key;
10466
10817
 
10467
- const deleteButton = createElement("lexxy-node-delete-button");
10468
- figure.appendChild(deleteButton);
10469
-
10470
10818
  return figure
10471
10819
  }
10472
10820
 
@@ -10482,6 +10830,18 @@ class ActionTextAttachmentNode extends Ji {
10482
10830
  return this.contentType.startsWith("video/")
10483
10831
  }
10484
10832
 
10833
+ get label() {
10834
+ if (this.caption && this.altText && this.altText !== this.caption && this.altText !== this.fileName) {
10835
+ return `${this.caption}. ${this.altText}`
10836
+ } else {
10837
+ return this.caption || this.altText || this.fileName || ""
10838
+ }
10839
+ }
10840
+
10841
+ focusCaption() {
10842
+ return this.editor.getRootElement()?.closest("lexxy-editor")?.captionEditor.open(this.getKey()) ?? false
10843
+ }
10844
+
10485
10845
  #createDOMForPendingPreview() {
10486
10846
  const figure = this.createAttachmentFigure(false);
10487
10847
  figure.appendChild(this.#createDOMForFile());
@@ -10621,8 +10981,9 @@ class ActionTextAttachmentNode extends Ji {
10621
10981
  }
10622
10982
 
10623
10983
  #swapToPreviewDOM(figure, previewSrc) {
10984
+ const altText = this.editor.read(() => this.getLatest().altText);
10624
10985
  this.#swapFigureContent(figure, "attachment--file", "attachment--preview", () => {
10625
- const img = createElement("img", { src: previewSrc, draggable: false, alt: this.altText });
10986
+ const img = createElement("img", { src: previewSrc, draggable: false, alt: altText });
10626
10987
  img.onerror = () => this.#swapPreviewToFileDOM(img);
10627
10988
  const container = createElement("div", { className: "attachment__container" });
10628
10989
  container.appendChild(img);
@@ -10672,54 +11033,17 @@ class ActionTextAttachmentNode extends Ji {
10672
11033
  }
10673
11034
 
10674
11035
  #createEditableCaption() {
10675
- const caption = createElement("figcaption", { className: "attachment__caption" });
10676
- const input = createElement("textarea", {
10677
- value: this.caption,
10678
- placeholder: this.fileName,
10679
- rows: "1"
11036
+ const caption = createElement("figcaption", { className: "attachment__caption attachment__caption--editable" });
11037
+ const text = createElement("span", { className: "attachment__caption-text", textContent: this.captionLabel });
11038
+ caption.appendChild(text);
11039
+ caption.toggleAttribute("data-placeholder", !this.caption);
11040
+ caption.addEventListener("mousedown", event => event.preventDefault());
11041
+ caption.addEventListener("click", event => {
11042
+ event.stopPropagation();
11043
+ this.focusCaption();
10680
11044
  });
10681
-
10682
- input.addEventListener("focusin", () => input.placeholder = "Add caption...");
10683
- input.addEventListener("blur", (event) => this.#handleCaptionInputBlurred(event));
10684
- input.addEventListener("keydown", (event) => this.#handleCaptionInputKeydown(event));
10685
- input.addEventListener("copy", (event) => event.stopPropagation());
10686
- input.addEventListener("cut", (event) => event.stopPropagation());
10687
- input.addEventListener("paste", (event) => event.stopPropagation());
10688
-
10689
- caption.appendChild(input);
10690
-
10691
11045
  return caption
10692
11046
  }
10693
-
10694
- #handleCaptionInputBlurred(event) {
10695
- this.#updateCaptionValueFromInput(event.target);
10696
- }
10697
-
10698
- #updateCaptionValueFromInput(input) {
10699
- input.placeholder = this.fileName;
10700
- this.editor.update(() => {
10701
- this.getWritable().caption = input.value;
10702
- });
10703
- }
10704
-
10705
- #handleCaptionInputKeydown(event) {
10706
- if (event.key === "Enter") {
10707
- event.preventDefault();
10708
- event.target.blur();
10709
-
10710
- this.editor.update(() => {
10711
- // Place the cursor after the current image
10712
- this.selectNext(0, 0);
10713
- }, {
10714
- tag: Jn
10715
- });
10716
- }
10717
-
10718
- // Stop all keydown events from bubbling to the Lexical root element.
10719
- // The caption textarea is outside Lexical's content model and should
10720
- // handle its own keyboard events natively (Ctrl+A, Ctrl+C, Ctrl+X, etc.).
10721
- event.stopPropagation();
10722
- }
10723
11047
  }
10724
11048
 
10725
11049
  function $createActionTextAttachmentNode(...args) {
@@ -10879,14 +11203,11 @@ class HorizontalDividerNode extends Ji {
10879
11203
  super(key);
10880
11204
  }
10881
11205
 
11206
+ // The hr already provides separator semantics; a figure boundary would be redundant.
10882
11207
  createDOM() {
10883
- const figure = createElement("figure", { className: "horizontal-divider" });
10884
- const hr = createElement("hr");
10885
-
10886
- figure.appendChild(hr);
10887
-
10888
- const deleteButton = createElement("lexxy-node-delete-button");
10889
- figure.appendChild(deleteButton);
11208
+ const figure = createElement("figure", { className: "horizontal-divider", role: "presentation" });
11209
+ figure.appendChild(createElement("hr"));
11210
+ figure.dataset.lexicalNodeKey = this.__key;
10890
11211
 
10891
11212
  return figure
10892
11213
  }
@@ -10903,6 +11224,10 @@ class HorizontalDividerNode extends Ji {
10903
11224
  return false
10904
11225
  }
10905
11226
 
11227
+ get label() {
11228
+ return "Horizontal divider"
11229
+ }
11230
+
10906
11231
  exportDOM() {
10907
11232
  const hr = createElement("hr");
10908
11233
  return { element: hr }
@@ -11168,199 +11493,376 @@ var theme = {
11168
11493
  }
11169
11494
  };
11170
11495
 
11171
- class UploadRequests {
11172
- #requestsByKey = new Map()
11173
-
11174
- track(key, request) {
11175
- this.#requestsByKey.set(key, request);
11496
+ class ImageGalleryNode extends Bi {
11497
+ $config() {
11498
+ return this.config("image_gallery", {
11499
+ extends: Bi,
11500
+ })
11176
11501
  }
11177
11502
 
11178
- forget(key) {
11179
- this.#requestsByKey.delete(key);
11503
+ static transform() {
11504
+ return (gallery) => {
11505
+ gallery.unwrapEmptyNode()
11506
+ || gallery.replaceWithSingularChild()
11507
+ || gallery.splitAroundInvalidChild();
11508
+ }
11180
11509
  }
11181
11510
 
11182
- abort(key) {
11183
- const request = this.#requestsByKey.get(key);
11184
- if (request) {
11185
- this.#requestsByKey.delete(key);
11186
- request.abort();
11511
+ static importDOM() {
11512
+ return {
11513
+ div: (element) => {
11514
+ if (!this.#isGalleryElement(element)) return null
11515
+
11516
+ return {
11517
+ conversion: () => {
11518
+ return {
11519
+ node: $createImageGalleryNode()
11520
+ }
11521
+ },
11522
+ priority: 2
11523
+ }
11524
+ }
11187
11525
  }
11188
11526
  }
11189
11527
 
11190
- clear() {
11191
- this.#requestsByKey.clear();
11528
+ static canCollapseWith(node) {
11529
+ return $isImageGalleryNode(node) || this.isValidChild(node)
11192
11530
  }
11193
- }
11194
11531
 
11195
- /**
11196
- * Copyright (c) Meta Platforms, Inc. and affiliates.
11197
- *
11198
- * This source code is licensed under the MIT license found in the
11199
- * LICENSE file in the root directory of this source tree.
11200
- *
11201
- */
11532
+ static isValidChild(node) {
11533
+ return $isActionTextAttachmentNode(node) && node.isPreviewableImage
11534
+ }
11202
11535
 
11203
- const Ke$1=/^(\d+(?:\.\d+)?)px$/,Ae$1={BOTH:3,COLUMN:2,NO_STATUS:0,ROW:1};let Ee$1 = class Ee extends Bi{__colSpan;__rowSpan;__headerState;__width;__backgroundColor;__verticalAlign;static getType(){return "tablecell"}static clone(e){return new Ee(e.__headerState,e.__colSpan,e.__width,e.__key)}afterCloneFrom(e){super.afterCloneFrom(e),this.__rowSpan=e.__rowSpan,this.__backgroundColor=e.__backgroundColor,this.__verticalAlign=e.__verticalAlign,this.__colSpan=e.__colSpan,this.__headerState=e.__headerState,this.__width=e.__width;}static importDOM(){return {td:e=>({conversion:Me$1,priority:0}),th:e=>({conversion:Me$1,priority:0})}}static importJSON(e){return $e$1().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setHeaderStyles(e.headerState).setColSpan(e.colSpan||1).setRowSpan(e.rowSpan||1).setWidth(e.width||void 0).setBackgroundColor(e.backgroundColor||null).setVerticalAlign(e.verticalAlign||void 0)}constructor(e=Ae$1.NO_STATUS,t=1,n,o){super(o),this.__colSpan=t,this.__rowSpan=1,this.__headerState=e,this.__width=n,this.__backgroundColor=null,this.__verticalAlign=void 0;}createDOM(t){const n=document.createElement(this.getTag());return this.__width&&(n.style.width=`${this.__width}px`),this.__colSpan>1&&(n.colSpan=this.__colSpan),this.__rowSpan>1&&(n.rowSpan=this.__rowSpan),null!==this.__backgroundColor&&(n.style.backgroundColor=this.__backgroundColor),ke$1(this.__verticalAlign)&&(n.style.verticalAlign=this.__verticalAlign),mc(n,t.theme.tableCell,this.hasHeader()&&t.theme.tableCellHeader),n}exportDOM(e){const t=super.exportDOM(e);if(Ys(t.element)){const e=t.element;e.setAttribute("data-temporary-table-cell-lexical-key",this.getKey()),e.style.border="1px solid black",this.__colSpan>1&&(e.colSpan=this.__colSpan),this.__rowSpan>1&&(e.rowSpan=this.__rowSpan),e.style.width=`${this.getWidth()||75}px`,e.style.verticalAlign=this.getVerticalAlign()||"top",e.style.textAlign="start",null===this.__backgroundColor&&this.hasHeader()&&(e.style.backgroundColor="#f2f3f5");}return t}exportJSON(){return {...super.exportJSON(),...ke$1(this.__verticalAlign)&&{verticalAlign:this.__verticalAlign},backgroundColor:this.getBackgroundColor(),colSpan:this.__colSpan,headerState:this.__headerState,rowSpan:this.__rowSpan,width:this.getWidth()}}getColSpan(){return this.getLatest().__colSpan}setColSpan(e){const t=this.getWritable();return t.__colSpan=e,t}getRowSpan(){return this.getLatest().__rowSpan}setRowSpan(e){const t=this.getWritable();return t.__rowSpan=e,t}getTag(){return this.hasHeader()?"th":"td"}setHeaderStyles(e,t=Ae$1.BOTH){const n=this.getWritable();return n.__headerState=e&t|n.__headerState&~t,n}getHeaderStyles(){return this.getLatest().__headerState}setWidth(e){const t=this.getWritable();return t.__width=e,t}getWidth(){return this.getLatest().__width}getBackgroundColor(){return this.getLatest().__backgroundColor}setBackgroundColor(e){const t=this.getWritable();return t.__backgroundColor=e,t}getVerticalAlign(){return this.getLatest().__verticalAlign}setVerticalAlign(e){const t=this.getWritable();return t.__verticalAlign=e||void 0,t}toggleHeaderStyle(e){const t=this.getWritable();return (t.__headerState&e)===e?t.__headerState-=e:t.__headerState+=e,t}hasHeaderState(e){return (this.getHeaderStyles()&e)===e}hasHeader(){return this.getLatest().__headerState!==Ae$1.NO_STATUS}updateDOM(e){return e.__headerState!==this.__headerState||e.__width!==this.__width||e.__colSpan!==this.__colSpan||e.__rowSpan!==this.__rowSpan||e.__backgroundColor!==this.__backgroundColor||e.__verticalAlign!==this.__verticalAlign}isShadowRoot(){return true}collapseAtStart(){return true}canBeEmpty(){return false}canIndent(){return false}};function ke$1(e){return "middle"===e||"bottom"===e}function Me$1(e){const t=e,n=e.nodeName.toLowerCase();let o;Ke$1.test(t.style.width)&&(o=parseFloat(t.style.width));let r=Ae$1.NO_STATUS;if("th"===n){const e=t.getAttribute("scope");if("col"===e)r=Ae$1.COLUMN;else if("row"===e)r=Ae$1.ROW;else {const e=t.parentElement,n=Ys(e)&&"tr"===e.nodeName.toLowerCase()&&Ys(e.parentElement)&&("thead"===e.parentElement.nodeName.toLowerCase()||0===e.rowIndex),o=0===t.cellIndex;n&&(r|=Ae$1.ROW),o&&(r|=Ae$1.COLUMN),r===Ae$1.NO_STATUS&&(r=Ae$1.ROW);}}const l=$e$1(r,t.colSpan,o);l.__rowSpan=t.rowSpan;const s=t.style.backgroundColor;""!==s&&(l.__backgroundColor=s);const i=t.style.verticalAlign;ke$1(i)&&(l.__verticalAlign=i);const c=t.style,a=(c&&c.textDecoration||"").split(" "),u="700"===c.fontWeight||"bold"===c.fontWeight,h=a.includes("line-through"),C="italic"===c.fontStyle,_=a.includes("underline"),S=c.color;return {after:e=>{const t=[];let n=null;const o=()=>{if(n){const e=n.getFirstChild();sr(e)&&1===n.getChildrenSize()&&e.remove();}};for(const r of e)if(Fs(r)||Tr(r)||sr(r)){if(Tr(r)&&(u&&r.toggleFormat("bold"),h&&r.toggleFormat("strikethrough"),C&&r.toggleFormat("italic"),_&&r.toggleFormat("underline"),S)){const e=r.getStyle();e.includes("color:")||r.setStyle(e+`color: ${S};`);}n?n.append(r):(n=eo().append(r),t.push(n));}else t.push(r),o(),n=null;return o(),0===t.length&&t.push(eo()),t},node:l}}function $e$1(e=Ae$1.NO_STATUS,t=1,n){return zs(new Ee$1(e,t,n))}function We$1(e){return e instanceof Ee$1}const ze$1=re$5("INSERT_TABLE_COMMAND");function Le$1(e,...t){const n=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",e);for(const e of t)o.append("v",e);throw n.search=o.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}let He$1 = class He extends Bi{__height;static getType(){return "tablerow"}static clone(e){return new He(e.__height,e.__key)}afterCloneFrom(e){super.afterCloneFrom(e),this.__height=e.__height;}static importDOM(){return {tr:e=>({conversion:Be$1,priority:0})}}static importJSON(e){return Pe$1().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setHeight(e.height)}constructor(e,t){super(t),this.__height=e;}exportJSON(){const e=this.getHeight();return {...super.exportJSON(),...void 0===e?void 0:{height:e}}}createDOM(t){const n=document.createElement("tr");return this.__height&&(n.style.height=`${this.__height}px`),mc(n,t.theme.tableRow),n}extractWithChild(e,t,n){return "html"===n}isShadowRoot(){return true}setHeight(e){const t=this.getWritable();return t.__height=e,t}getHeight(){return this.getLatest().__height}updateDOM(e){return e.__height!==this.__height}canBeEmpty(){return false}canIndent(){return false}};function Be$1(e){const n=e;let o;return Ke$1.test(n.style.height)&&(o=parseFloat(n.style.height)),{after:e=>Ht$3(e,We$1),node:Pe$1(o)}}function Pe$1(e){return zs(new He$1(e))}function De$1(e){return e instanceof He$1}const Ie$1="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,Ue$1=Ie$1&&"documentMode"in document?document.documentMode:null,Je$1=Ie$1&&/^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);function Xe$1(e,t,n=true){const o=Fn();for(let r=0;r<e;r++){const e=Pe$1();for(let o=0;o<t;o++){let t=Ae$1.NO_STATUS;"object"==typeof n?(0===r&&n.rows&&(t|=Ae$1.ROW),0===o&&n.columns&&(t|=Ae$1.COLUMN)):n&&(0===r&&(t|=Ae$1.ROW),0===o&&(t|=Ae$1.COLUMN));const l=$e$1(t),s=eo();s.append(kr()),l.append(s),e.append(l);}o.append(e);}return o}function Ye(e){const t=dl(e,e=>We$1(e));return We$1(t)?t:null}function qe$1(e){const t=dl(e,e=>De$1(e));if(De$1(t))return t;throw new Error("Expected table cell to be inside of table row.")}function je$1(e){const t=dl(e,e=>Rn(e));if(Rn(t))return t;throw new Error("Expected table cell to be inside of table.")}function Ve$1(e){const t=qe$1(e);return je$1(t).getChildren().findIndex(e=>e.is(t))}function Ge$1(e){return qe$1(e).getChildren().findIndex(t=>t.is(e))}Ie$1&&"InputEvent"in window&&!Ue$1&&new window.InputEvent("input");const tt=(e,t)=>e===Ae$1.BOTH||e===t?t:Ae$1.NO_STATUS;function nt(e=true){const t=Qr();Fr(t)||Ot(t)||Le$1(188);const n=t.anchor.getNode(),o=t.focus.getNode(),[r]=yt(n),[l,,s]=yt(o),[,i,c]=wt(s,l,r),{startRow:a}=c,{startRow:u}=i;return e?rt(a+r.__rowSpan>u+l.__rowSpan?r:l,true):rt(u<a?l:r,false)}function rt(e,t=true){const[,,n]=yt(e),[o,r]=wt(n,e,e),l=o[0].length,{startRow:s}=r;let i=null;if(t){const t=s+e.__rowSpan-1,r=o[t],c=Pe$1();for(let e=0;e<l;e++){const{cell:n,startRow:o}=r[e];if(o+n.__rowSpan-1<=t){const t=r[e].cell.__headerState,n=tt(t,Ae$1.COLUMN);c.append($e$1(n).append(eo()));}else n.setRowSpan(n.__rowSpan+1);}const a=n.getChildAtIndex(t);De$1(a)||Le$1(256),a.insertAfter(c),i=c;}else {const e=s,t=o[e],r=Pe$1();for(let n=0;n<l;n++){const{cell:o,startRow:l}=t[n];if(l===e){const e=t[n].cell.__headerState,o=tt(e,Ae$1.COLUMN);r.append($e$1(o).append(eo()));}else o.setRowSpan(o.__rowSpan+1);}const c=n.getChildAtIndex(e);De$1(c)||Le$1(257),c.insertBefore(r),i=r;}return i}function st(e=true){const t=Qr();Fr(t)||Ot(t)||Le$1(188);const n=t.anchor.getNode(),o=t.focus.getNode(),[r]=yt(n),[l,,s]=yt(o),[,i,c]=wt(s,l,r),{startColumn:a}=c,{startColumn:u}=i;return e?ct(a+r.__colSpan>u+l.__colSpan?r:l,true):ct(u<a?l:r,false)}function ct(e,t=true,n=true){const[,,o]=yt(e),[r,l]=wt(o,e,e),s=r.length,{startColumn:i}=l,c=t?i+e.__colSpan-1:i-1,a=o.getFirstChild();De$1(a)||Le$1(120);let u=null;function h(e=Ae$1.NO_STATUS){const t=$e$1(e).append(eo());return null===u&&(u=t),t}let d=a;e:for(let e=0;e<s;e++){if(0!==e){const e=d.getNextSibling();De$1(e)||Le$1(121),d=e;}const t=r[e],n=t[c<0?0:c].cell.__headerState,o=tt(n,Ae$1.ROW);if(c<0){mt(d,h(o));continue}const{cell:l,startColumn:s,startRow:i}=t[c];if(s+l.__colSpan-1<=c){let n=l,r=i,s=c;for(;r!==e&&n.__rowSpan>1;){if(s-=l.__colSpan,!(s>=0)){d.append(h(o));continue e}{const{cell:e,startRow:o}=t[s];n=e,r=o;}}n.insertAfter(h(o));}else l.setColSpan(l.__colSpan+1);}null!==u&&n&&gt(u);const f=o.getColWidths();if(f){const e=[...f],t=c<0?0:c,n=e[t];e.splice(t,0,n),o.setColWidths(e);}return u}function ut(){const e=Qr();Fr(e)||Ot(e)||Le$1(188);const[t,n]=e.isBackward()?[e.focus.getNode(),e.anchor.getNode()]:[e.anchor.getNode(),e.focus.getNode()],[o,,r]=yt(t),[l]=yt(n),[s,i,c]=wt(r,o,l),{startRow:a}=i,{startRow:u}=c,h=u+l.__rowSpan-1;if(s.length===h-a+1)return void r.remove();const d=s[0].length,f=s[h+1],g=r.getChildAtIndex(h+1);for(let e=h;e>=a;e--){for(let t=d-1;t>=0;t--){const{cell:n,startRow:o,startColumn:r}=s[e][t];if(r===t){if(o<a||o+n.__rowSpan-1>h){const e=Math.max(o,a),t=Math.min(n.__rowSpan+o-1,h),r=e<=t?t-e+1:0;n.setRowSpan(n.__rowSpan-r);}if(o>=a&&o+n.__rowSpan-1>h&&e===h){null===g&&Le$1(122);let o=null;for(let n=0;n<t;n++){const t=f[n],r=t.cell;t.startRow===e+1&&(o=r),r.__colSpan>1&&(n+=r.__colSpan-1);}null===o?mt(g,n):o.insertAfter(n);}}}const t=r.getChildAtIndex(e);De$1(t)||Le$1(206,String(e)),t.remove();}if(void 0!==f){const{cell:e}=f[0];gt(e);}else {const e=s[a-1],{cell:t}=e[0];gt(t);}}function dt(){const e=Qr();Fr(e)||Ot(e)||Le$1(188);const t=e.anchor.getNode(),n=e.focus.getNode(),[o,,r]=yt(t),[l]=yt(n),[s,i,c]=wt(r,o,l),{startColumn:a}=i,{startRow:u,startColumn:h}=c,d=Math.min(a,h),f=Math.max(a+o.__colSpan-1,h+l.__colSpan-1),g=f-d+1;if(s[0].length===f-d+1)return r.selectPrevious(),void r.remove();const m=s.length;for(let e=0;e<m;e++)for(let t=d;t<=f;t++){const{cell:n,startColumn:o}=s[e][t];if(o<d){if(t===d){const e=d-o;n.setColSpan(n.__colSpan-Math.min(g,n.__colSpan-e));}}else if(o+n.__colSpan-1>f){if(t===f){const e=f-o+1;n.setColSpan(n.__colSpan-e);}}else n.remove();}const p=s[u],C=a>h?p[a+o.__colSpan]:p[h+l.__colSpan];if(void 0!==C){const{cell:e}=C;gt(e);}else {const e=h<a?p[h-1]:p[a-1],{cell:t}=e;gt(t);}const _=r.getColWidths();if(_){const e=[..._];e.splice(d,g),r.setColWidths(e);}}function gt(e){const t=e.getFirstDescendant();null==t?e.selectStart():t.getParentOrThrow().selectStart();}function mt(e,t){const n=e.getFirstChild();null!==n?n.insertBefore(t):e.append(t);}function pt(e){if(0===e.length)return null;const t=je$1(e[0]),[n]=bt(t,null,null);let o=1/0,r=-1/0,l=1/0,s=-1/0;const i=new Set;for(const t of n)for(const n of t){if(!n||!n.cell)continue;const t=n.cell.getKey();if(!i.has(t)&&e.some(e=>e.is(n.cell))){i.add(t);const e=n.startRow,c=n.startColumn,a=n.cell.__rowSpan||1,u=n.cell.__colSpan||1;o=Math.min(o,e),r=Math.max(r,e+a-1),l=Math.min(l,c),s=Math.max(s,c+u-1);}}if(o===1/0||l===1/0)return null;const c=r-o+1,a=s-l+1,u=n[o][l];if(!u.cell)return null;const h=u.cell;h.setColSpan(a),h.setRowSpan(c);const d=new Set([h.getKey()]);for(let e=o;e<=r;e++)for(let t=l;t<=s;t++){const o=n[e][t];if(!o.cell)continue;const r=o.cell,l=r.getKey();if(!d.has(l)){d.add(l);Ct(r)||h.append(...r.getChildren()),r.remove();}}return 0===h.getChildrenSize()&&h.append(eo()),h}function Ct(e){if(1!==e.getChildrenSize())return false;const t=e.getFirstChildOrThrow();return !(!no(t)||!t.isEmpty())}function St(e){const[t,n,o]=yt(e),r=t.__colSpan,l=t.__rowSpan;if(1===r&&1===l)return;const[s,i]=wt(o,t,t),{startColumn:c,startRow:a}=i,u=t.__headerState&Ae$1.COLUMN,h=Array.from({length:r},(e,t)=>{let n=u;for(let e=0;0!==n&&e<s.length;e++)n&=s[e][t+c].cell.__headerState;return n}),d=t.__headerState&Ae$1.ROW,f=Array.from({length:l},(e,t)=>{let n=d;for(let e=0;0!==n&&e<s[0].length;e++)n&=s[t+a][e].cell.__headerState;return n});if(r>1){for(let e=1;e<r;e++)t.insertAfter($e$1(h[e]|f[0]).append(eo()));t.setColSpan(1);}if(l>1){let e;for(let t=1;t<l;t++){const o=a+t,l=s[o];e=(e||n).getNextSibling(),De$1(e)||Le$1(125);let i=null;for(let e=0;e<c;e++){const t=l[e],n=t.cell;t.startRow===o&&(i=n),n.__colSpan>1&&(e+=n.__colSpan-1);}if(null===i)for(let n=r-1;n>=0;n--)mt(e,$e$1(h[n]|f[t]).append(eo()));else for(let e=r-1;e>=0;e--)i.insertAfter($e$1(h[e]|f[t]).append(eo()));}t.setRowSpan(1);}}function wt(e,t,n){const[o,r,l]=bt(e,t,n);return null===r&&Le$1(207),null===l&&Le$1(208),[o,r,l]}function bt(e,t,n){const o=[];let r=null,l=null;function s(e){let t=o[e];return void 0===t&&(o[e]=t=[]),t}const i=e.getChildren();for(let e=0;e<i.length;e++){const o=i[e];De$1(o)||Le$1(209);const c=s(e);for(let a=o.getFirstChild(),u=0;null!=a;a=a.getNextSibling()){for(We$1(a)||Le$1(147);void 0!==c[u];)u++;const o={cell:a,startColumn:u,startRow:e},{__rowSpan:h,__colSpan:d}=a;for(let t=0;t<h&&!(e+t>=i.length);t++){const n=s(e+t);for(let e=0;e<d;e++)n[u+e]=o;}null!==t&&null===r&&t.is(a)&&(r=o),null!==n&&null===l&&n.is(a)&&(l=o);}}return [o,r,l]}function yt(e){let t;if(e instanceof Ee$1)t=e;else if("__type"in e){const o=dl(e,We$1);We$1(o)||Le$1(148),t=o;}else {const o=dl(e.getNode(),We$1);We$1(o)||Le$1(148),t=o;}const o=t.getParent();De$1(o)||Le$1(149);const r=o.getParent();return Rn(r)||Le$1(210),[t,o,r]}function Nt(e,t,n){let o,r=Math.min(t.startColumn,n.startColumn),l=Math.min(t.startRow,n.startRow),s=Math.max(t.startColumn+t.cell.__colSpan-1,n.startColumn+n.cell.__colSpan-1),i=Math.max(t.startRow+t.cell.__rowSpan-1,n.startRow+n.cell.__rowSpan-1);do{o=false;for(let t=0;t<e.length;t++)for(let n=0;n<e[0].length;n++){const c=e[t][n];if(!c)continue;const a=c.startColumn+c.cell.__colSpan-1,u=c.startRow+c.cell.__rowSpan-1,h=c.startColumn<=s&&a>=r,d=c.startRow<=i&&u>=l;if(h&&d){const e=Math.min(r,c.startColumn),t=Math.max(s,a),n=Math.min(l,c.startRow),h=Math.max(i,u);e===r&&t===s&&n===l&&h===i||(r=e,s=t,l=n,i=h,o=true);}}}while(o);return {maxColumn:s,maxRow:i,minColumn:r,minRow:l}}function Tt(e){const[t,,n]=yt(e),o=n.getChildren(),r=o.length,l=o[0].getChildren().length,s=new Array(r);for(let e=0;e<r;e++)s[e]=new Array(l);for(let e=0;e<r;e++){const n=o[e].getChildren();let r=0;for(let o=0;o<n.length;o++){for(;s[e][r];)r++;const l=n[o],i=l.__rowSpan||1,c=l.__colSpan||1;for(let t=0;t<i;t++)for(let n=0;n<c;n++)s[e+t][r+n]=l;if(t===l)return {colSpan:c,columnIndex:r,rowIndex:e,rowSpan:i};r+=c;}}return null}function Ft(e){const[[t,o,r,l],[s,i,c,a]]=["anchor","focus"].map(t=>{const o=e[t].getNode(),r=dl(o,We$1);We$1(r)||Le$1(238,t,o.getKey(),o.getType());const l=r.getParent();De$1(l)||Le$1(239,t);const s=l.getParent();return Rn(s)||Le$1(240,t),[o,r,l,s]});return l.is(a)||Le$1(241),{anchorCell:o,anchorNode:t,anchorRow:r,anchorTable:l,focusCell:i,focusNode:s,focusRow:c,focusTable:a}}class Rt{tableKey;anchor;focus;_cachedNodes;dirty;constructor(e,t,n){this.anchor=t,this.focus=n,t._selection=this,n._selection=this,this._cachedNodes=null,this.dirty=false,this.tableKey=e;}getStartEndPoints(){return [this.anchor,this.focus]}isValid(){if("root"===this.tableKey||"root"===this.anchor.key||"element"!==this.anchor.type||"root"===this.focus.key||"element"!==this.focus.type)return false;const e=Yo(this.tableKey),t=Yo(this.anchor.key),n=Yo(this.focus.key);return null!==e&&null!==t&&null!==n}isBackward(){return this.focus.isBefore(this.anchor)}getCachedNodes(){return this._cachedNodes}setCachedNodes(e){this._cachedNodes=e;}is(e){return Ot(e)&&this.tableKey===e.tableKey&&this.anchor.is(e.anchor)&&this.focus.is(e.focus)}set(e,t,n){this.dirty=this.dirty||e!==this.tableKey||t!==this.anchor.key||n!==this.focus.key,this.tableKey=e,this.anchor.key=t,this.focus.key=n,this._cachedNodes=null;}clone(){return new Rt(this.tableKey,Mr(this.anchor.key,this.anchor.offset,this.anchor.type),Mr(this.focus.key,this.focus.offset,this.focus.type))}isCollapsed(){return false}extract(){return this.getNodes()}insertRawText(e){}insertText(){}hasFormat(e){let t=0;this.getNodes().filter(We$1).forEach(e=>{const n=e.getFirstChild();no(n)&&(t|=n.getTextFormat());});const n=z$7[e];return 0!==(t&n)}insertNodes(e){const t=this.focus.getNode();Wi(t)||Le$1(151);St$3(t.select(0,t.getChildrenSize())).insertNodes(e);}getShape(){const{anchorCell:e,focusCell:t}=Ft(this),n=Tt(e);null===n&&Le$1(153);const o=Tt(t);null===o&&Le$1(155);const r=Math.min(n.columnIndex,o.columnIndex),l=Math.max(n.columnIndex+n.colSpan-1,o.columnIndex+o.colSpan-1),s=Math.min(n.rowIndex,o.rowIndex),i=Math.max(n.rowIndex+n.rowSpan-1,o.rowIndex+o.rowSpan-1);return {fromX:Math.min(r,l),fromY:Math.min(s,i),toX:Math.max(r,l),toY:Math.max(s,i)}}getNodes(){if(!this.isValid())return [];const e=this._cachedNodes;if(null!==e)return e;const{anchorTable:t,anchorCell:n,focusCell:o}=Ft(this),r=o.getParents()[1];if(r!==t){if(t.isParentOf(o)){const e=r.getParent();null==e&&Le$1(159),this.set(this.tableKey,o.getKey(),e.getKey());}else {const e=t.getParent();null==e&&Le$1(158),this.set(this.tableKey,e.getKey(),o.getKey());}return this.getNodes()}const[l,s,i]=wt(t,n,o),{minColumn:c,maxColumn:a,minRow:u,maxRow:h}=Nt(l,s,i),d=new Map([[t.getKey(),t]]);let f=null;for(let e=u;e<=h;e++)for(let t=c;t<=a;t++){const{cell:n}=l[e][t],o=n.getParent();De$1(o)||Le$1(160),o!==f&&(d.set(o.getKey(),o),f=o),d.has(n.getKey())||Et(n,e=>{d.set(e.getKey(),e);});}const g=Array.from(d.values());return mi()||(this._cachedNodes=g),g}getTextContent(){const e=this.getNodes().filter(e=>We$1(e));let t="";for(let n=0;n<e.length;n++){const o=e[n],r=o.__parent,l=(e[n+1]||{}).__parent;t+=o.getTextContent()+(l!==r?"\n":"\t");}return t}}function Ot(e){return e instanceof Rt}function Kt(){const e=Mr("root",0,"element"),t=Mr("root",0,"element");return new Rt("root",e,t)}function At(e,t,n){e.getKey(),t.getKey(),n.getKey();const o=Qr(),r=Ot(o)?o.clone():Kt();return r.set(e.getKey(),t.getKey(),n.getKey()),r}function Et(e,t){const n=[[e]];for(let e=n.at(-1);void 0!==e&&n.length>0;e=n.at(-1)){const o=e.pop();void 0===o?n.pop():false!==t(o)&&Wi(o)&&n.push(o.getChildren());}}function kt(e,t=Zs()){const n=Yo(e);Rn(n)||Le$1(231,e);const o=Lt(n,t.getElementByKey(e));return null===o&&Le$1(232,e),{tableElement:o,tableNode:n}}class Mt{observers;nextFocus;shouldCheckSelectionForTable;constructor(){this.observers=new Map,this.nextFocus=null,this.shouldCheckSelectionForTable=null;}setNextFocus(e){this.nextFocus=e;}getAndClearNextFocus(){const{nextFocus:e}=this;return null!==e&&(this.nextFocus=null),e}setShouldCheckSelectionForTable(e){this.shouldCheckSelectionForTable=e;}getAndClearShouldCheckSelectionForTable(){const{shouldCheckSelectionForTable:e}=this;return e?(this.shouldCheckSelectionForTable=null,e):null}}class $t{focusX;focusY;listenersToRemove;table;isHighlightingCells;anchorX;anchorY;tableNodeKey;anchorCell;focusCell;anchorCellNodeKey;focusCellNodeKey;editor;tableSelection;hasHijackedSelectionStyles;isSelecting;pointerType;abortController;listenerOptions;constructor(e,t){this.isHighlightingCells=false,this.anchorX=-1,this.anchorY=-1,this.focusX=-1,this.focusY=-1,this.listenersToRemove=new Set,this.tableNodeKey=t,this.editor=e,this.table={columns:0,domRows:[],rows:0},this.tableSelection=null,this.anchorCellNodeKey=null,this.focusCellNodeKey=null,this.anchorCell=null,this.focusCell=null,this.hasHijackedSelectionStyles=false,this.isSelecting=false,this.pointerType=null,this.abortController=new AbortController,this.listenerOptions={signal:this.abortController.signal},this.trackTable();}getTable(){return this.table}removeListeners(){this.abortController.abort("removeListeners"),Array.from(this.listenersToRemove).forEach(e=>e()),this.listenersToRemove.clear();}$lookup(){return kt(this.tableNodeKey,this.editor)}trackTable(){const e=new MutationObserver(e=>{this.editor.getEditorState().read(()=>{let t=false;for(let n=0;n<e.length;n++){const o=e[n].target.nodeName;if("TABLE"===o||"TBODY"===o||"THEAD"===o||"TR"===o){t=true;break}}if(!t)return;const{tableNode:n,tableElement:o}=this.$lookup();this.table=Gt(n,o);},{editor:this.editor});});this.editor.getEditorState().read(()=>{const{tableNode:t,tableElement:n}=this.$lookup();this.table=Gt(t,n),e.observe(n,{attributes:true,childList:true,subtree:true});},{editor:this.editor});}$clearHighlight(e=true){const t=this.editor;this.isHighlightingCells=false,this.anchorX=-1,this.anchorY=-1,this.focusX=-1,this.focusY=-1,this.tableSelection=null,this.anchorCellNodeKey=null,this.focusCellNodeKey=null,this.anchorCell=null,this.focusCell=null,this.hasHijackedSelectionStyles=false,this.$enableHighlightStyle();const{tableNode:n,tableElement:o}=this.$lookup();Qt(t,Gt(n,o),null),e&&null!==Qr()&&(es(null),t.dispatchCommand(ie$4,void 0));}$enableHighlightStyle(){const e=this.editor,{tableElement:t}=this.$lookup();xc(t,e._config.theme.tableSelection),t.classList.remove("disable-selection"),this.hasHijackedSelectionStyles=false;}$disableHighlightStyle(){const{tableElement:t}=this.$lookup();mc(t,this.editor._config.theme.tableSelection),this.hasHijackedSelectionStyles=true;}$updateTableTableSelection(e){if(null!==e){e.tableKey!==this.tableNodeKey&&Le$1(233,e.tableKey,this.tableNodeKey);const t=this.editor;this.tableSelection=e,this.isHighlightingCells=true,this.$disableHighlightStyle(),this.updateDOMSelection(),Qt(t,this.table,this.tableSelection);}else this.$clearHighlight();}updateDOMSelection(){if(null!==this.anchorCell&&null!==this.focusCell){const e=Js(this.editor._window);e&&e.rangeCount>0&&e.removeAllRanges();}}$setFocusCellForSelection(e,t=false){const n=this.editor,{tableNode:o}=this.$lookup(),r=e.x,l=e.y;if(this.focusCell=e,!this.isHighlightingCells){(t||this.anchorX!==r||this.anchorY!==l||null!=this.tableSelection&&null!=this.anchorCellNodeKey)&&(this.isHighlightingCells=true,this.$disableHighlightStyle());}if(-1!==this.focusX&&-1!==this.focusY&&r===this.focusX&&l===this.focusY)return false;if(this.focusX=r,this.focusY=l,this.isHighlightingCells){const s=_n(o,e.elem);if(null!=this.tableSelection&&null!=this.anchorCellNodeKey){let e=s;if(null===e&&t&&(e=o.getCellNodeFromCords(r,l,this.table)),null!==e){const t=this.$getAnchorTableCellOrThrow();return this.focusCellNodeKey=e.getKey(),this.tableSelection=At(o,t,e),es(this.tableSelection),n.dispatchCommand(ie$4,void 0),Qt(n,this.table,this.tableSelection),true}}}return false}$getAnchorTableCell(){return this.anchorCellNodeKey?Yo(this.anchorCellNodeKey):null}$getAnchorTableCellOrThrow(){const e=this.$getAnchorTableCell();return null===e&&Le$1(234),e}$getFocusTableCell(){return this.focusCellNodeKey?Yo(this.focusCellNodeKey):null}$getFocusTableCellOrThrow(){const e=this.$getFocusTableCell();return null===e&&Le$1(235),e}$setAnchorCellForSelection(e){this.isHighlightingCells=false,this.anchorCell=e,this.anchorX=e.x,this.anchorY=e.y,this.focusX=-1,this.focusY=-1,this.focusCell=null,this.focusCellNodeKey=null;const{tableNode:t}=this.$lookup(),n=_n(t,e.elem);if(null!==n){const e=n.getKey();null!=this.tableSelection?(this.tableSelection=this.tableSelection.clone(),this.tableSelection.set(t.getKey(),e,e)):this.tableSelection=At(t,n,n),this.anchorCellNodeKey=e;}}$formatCells(e){const t=Qr();Ot(t)||Le$1(236);const n=qr(),o=n.anchor,r=n.focus,l=t.getNodes().filter(We$1);l.length>0||Le$1(237);const s=l[0].getFirstChild(),i=no(s)?s.getFormatFlags(e,null):null;l.forEach(t=>{o.set(t.getKey(),0,"element"),r.set(t.getKey(),t.getChildrenSize(),"element"),n.formatText(e,i);}),es(t),this.editor.dispatchCommand(ie$4,void 0);}$clearText(){const{editor:e}=this,t=Yo(this.tableNodeKey);if(!Rn(t))throw new Error("Expected TableNode.");const n=Qr();Ot(n)||Le$1(253);const o=n.getNodes().filter(We$1),r=t.getFirstChild(),l=t.getLastChild();if(o.length>0&&null!==r&&null!==l&&De$1(r)&&De$1(l)&&o[0]===r.getFirstChild()&&o[o.length-1]===l.getLastChild()){t.selectPrevious();const n=t.getParent();return t.remove(),void(Vi(n)&&n.isEmpty()&&e.dispatchCommand(he$3,void 0))}o.forEach(e=>{if(Wi(e)){const t=eo(),n=kr();t.append(n),e.append(t),e.getChildren().forEach(e=>{e!==t&&e.remove();});}}),Qt(e,this.table,null),es(null),e.dispatchCommand(ie$4,void 0);}}const Wt="__lexicalTableSelection";function zt(e){return Ys(e)&&"TABLE"===e.nodeName}function Lt(e,t){if(!t)return t;const n=zt(t)?t:t.querySelector("table");return zt(n)||Le$1(341,e.constructor.name,e.getType(),e.getKey(),t.nodeName),n}function Ht(e){return e._window}function Bt(e,t){for(let n=t,o=null;null!==n;n=n.getParent()){if(e.is(n))return o;We$1(n)&&(o=n);}return null}const Pt=[[Ee$3,"down"],[we$1,"up"],[Ne$1,"backward"],[ke$2,"forward"]],Dt=[ye$2,me$3,fe$4],It=[Ae$3,Pe$2];function Ut(e,t){const n=e.getRootElement(),o=e._window;if(!n||!o)return ()=>{};const r=o=>{const r=o.target;if(0!==o.button||!qs(r)||!n.contains(r))return;const l=function(e){const t=jt(e);if(null===t)return null;let n=t.elem;for(;null!=n;){if("TABLE"===n.nodeName&&Wt in n&&n[Wt])return {cellElement:t,tableElement:n,tableObserver:n[Wt]};n=n.parentNode;}return null}(r);e.update(()=>{if(Ot(Qr())){for(const[e]of t.observers.values())e.$clearHighlight(false);es(null),e.dispatchCommand(ie$4,void 0);}if(!l)return;const{tableObserver:n,tableElement:r,cellElement:s}=l;!function(e,t,n,o,r,l){const s=e._window;if(!s)return;const i=t=>{if(r.isSelecting)return;r.isSelecting=true,null!==t&&null===r.anchorCell&&e.update(()=>{r.$setAnchorCellForSelection(t);});const n=()=>{r.isSelecting=false,s.removeEventListener("pointerup",n),s.removeEventListener("pointermove",i);},i=t=>{if(!(e=>!(1&~e.buttons))(t)&&r.isSelecting)return r.isSelecting=false,s.removeEventListener("pointerup",n),void s.removeEventListener("pointermove",i);if(!qs(t.target))return;let c=null;const a=!(Je$1||o.contains(t.target));if(a)c=Vt(o,t.target);else for(const e of document.elementsFromPoint(t.clientX,t.clientY))if(c=Vt(o,e),c)break;if(c){const t=c;null===r.anchorCell&&e.update(()=>{r.$setAnchorCellForSelection(t);}),null!==r.focusCell&&c.elem===r.focusCell.elem||(l.setNextFocus({focusCell:c,override:a,tableKey:r.tableNodeKey}),e.dispatchCommand(ie$4,void 0));}};s.addEventListener("pointerup",n,r.listenerOptions),s.addEventListener("pointermove",i,r.listenerOptions);};r.pointerType=t.pointerType;const c=Bs(r.tableNodeKey),a=Zr();if(Je$1&&t.shiftKey&&ln(a,c)&&(Fr(a)||Ot(a))){const e=a.anchor.getNode(),o=Bt(c,a.anchor.getNode());if(o)r.$setAnchorCellForSelection(Cn(r,o)),r.$setFocusCellForSelection(n),gn(t);else {(c.isBefore(e)?c.selectStart():c.selectEnd()).anchor.set(a.anchor.key,a.anchor.offset,a.anchor.type);}}else "touch"!==t.pointerType&&r.$setAnchorCellForSelection(n);i(n);}(e,o,s,r,n,t);});};return o.addEventListener("pointerdown",r),()=>{o.removeEventListener("pointerdown",r);}}function Jt(e,t,o,l,s){const i=o.getRootElement(),c=Ht(o);null!==i&&null!==c||Le$1(246);const a=new $t(o,e.getKey()),u=Lt(e,t);!function(e,t){null!==qt(e)&&Le$1(205);e[Wt]=t;}(u,a),a.listenersToRemove.add(()=>function(e,t){qt(e)===t&&delete e[Wt];}(u,a));const h=e=>{if(e.detail>=3&&qs(e.target)){null!==jt(e.target)&&e.preventDefault();}};u.addEventListener("mousedown",h,a.listenerOptions),a.listenersToRemove.add(()=>{u.removeEventListener("mousedown",h);});for(const[t,n]of Pt)a.listenersToRemove.add(o.registerCommand(t,t=>fn(o,t,n,e,a,s),so));a.listenersToRemove.add(o.registerCommand(De$2,t=>{const n=Qr();if(Ot(n)){const o=Bt(e,n.focus.getNode());if(null!==o)return gn(t),o.selectEnd(),true}return false},so));const d=t=>()=>{const o=Qr();if(!ln(o,e))return false;if(Ot(o))return a.$clearText(),true;if(Fr(o)){if(!We$1(Bt(e,o.anchor.getNode())))return false;const r=o.anchor.getNode(),l=o.focus.getNode(),s=e.isParentOf(r),i=e.isParentOf(l);if(s&&!i||i&&!s)return a.$clearText(),true;const c=dl(o.anchor.getNode(),e=>Wi(e)),u=c&&dl(c,e=>Wi(e)&&We$1(e.getParent()));if(!Wi(u)||!Wi(c))return false;if(t===me$3&&null===u.getPreviousSibling())return true}return false};for(const e of Dt)a.listenersToRemove.add(o.registerCommand(e,d(e),so));const f=t=>{const n=Qr();if(!Ot(n)&&!Fr(n))return false;const o=e.isParentOf(n.anchor.getNode());if(o!==e.isParentOf(n.focus.getNode())){const t=o?"anchor":"focus",r=o?"focus":"anchor",{key:l,offset:s,type:i}=n[r];return e[n[t].isBefore(n[r])?"selectPrevious":"selectNext"]()[r].set(l,s,i),false}return !!ln(n,e)&&(!!Ot(n)&&(t&&(t.preventDefault(),t.stopPropagation()),a.$clearText(),true))};for(const e of It)a.listenersToRemove.add(o.registerCommand(e,f,so));return a.listenersToRemove.add(o.registerCommand(je$2,e=>{const t=Qr();if(t){if(!Ot(t)&&!Fr(t))return false;V$4(o,Bt$3(e,ClipboardEvent)?e:null,et(t));const n=f(e);return Fr(t)?(t.removeText(),true):n}return false},so)),a.listenersToRemove.add(o.registerCommand(xe,t=>{const o=Qr();if(!ln(o,e))return false;if(Ot(o))return a.$formatCells(t),true;if(Fr(o)){const e=dl(o.anchor.getNode(),e=>We$1(e));if(!We$1(e))return false}return false},so)),a.listenersToRemove.add(o.registerCommand(Re$1,t=>{const n=Qr();if(!Ot(n)||!ln(n,e))return false;const o=n.anchor.getNode(),r=n.focus.getNode();if(!We$1(o)||!We$1(r))return false;if(function(e,t){if(Ot(e)){const n=e.anchor.getNode(),o=e.focus.getNode();if(t&&n&&o){const[e]=wt(t,n,o);return n.getKey()===e[0][0].cell.getKey()&&o.getKey()===e[e.length-1].at(-1).cell.getKey()}}return false}(n,e))return e.setFormat(t),true;const[l,s,i]=wt(e,o,r),c=Math.max(s.startRow+s.cell.__rowSpan-1,i.startRow+i.cell.__rowSpan-1),a=Math.max(s.startColumn+s.cell.__colSpan-1,i.startColumn+i.cell.__colSpan-1),u=Math.min(s.startRow,i.startRow),h=Math.min(s.startColumn,i.startColumn),d=new Set;for(let e=u;e<=c;e++)for(let n=h;n<=a;n++){const o=l[e][n].cell;if(d.has(o))continue;d.add(o),o.setFormat(t);const r=o.getChildren();for(let e=0;e<r.length;e++){const n=r[e];Wi(n)&&!n.isInline()&&n.setFormat(t);}}return true},so)),a.listenersToRemove.add(o.registerCommand(ge$3,t=>{const r=Qr();if(!ln(r,e))return false;if(Ot(r))return a.$clearHighlight(),false;if(Fr(r)){const l=dl(r.anchor.getNode(),e=>We$1(e));if(!We$1(l))return false;if("string"==typeof t){const n=pn(o,r,e);if(n)return mn(n,e,[kr(t)]),true}}return false},so)),l&&a.listenersToRemove.add(o.registerCommand(Fe$2,t=>{const o=Qr();if(!Fr(o)||!o.isCollapsed()||!ln(o,e))return false;const r=un(o.anchor.getNode());return !(null===r||!e.is(hn(r)))&&(gn(t),function(e,t){const o="next"===t?"getNextSibling":"getPreviousSibling",r="next"===t?"getFirstChild":"getLastChild",l=e[o]();if(Wi(l))return l.selectEnd();const s=dl(e,De$1);null===s&&Le$1(247);for(let e=s[o]();De$1(e);e=e[o]()){const t=e[r]();if(Wi(t))return t.selectEnd()}const i=dl(s,Rn);null===i&&Le$1(248);"next"===t?i.selectNext():i.selectPrevious();}(r,t.shiftKey?"previous":"next"),true)},so)),a.listenersToRemove.add(o.registerCommand(Ge$2,t=>e.isSelected(),so)),a.listenersToRemove.add(o.registerCommand(he$3,()=>{const t=Qr();if(!Fr(t)||!t.isCollapsed()||!ln(t,e))return false;const n=pn(o,t,e);return !!n&&(mn(n,e),true)},so)),a}function Xt(e,t){const o=Qr(),r=Zr(),l=e.getAndClearNextFocus();if(null!==l){const{tableKey:t,focusCell:n}=l,r=e.observers.get(t);r||Le$1(335,t);const[s]=r;if(Ot(o)&&o.tableKey===s.tableNodeKey)return (n.x!==s.focusX||n.y!==s.focusY)&&(s.$setFocusCellForSelection(n),true);if(null!==s.anchorCell&&null!==s.anchorCellNodeKey&&n.elem!==s.anchorCell.elem&&null!==s.tableSelection)return s.$setFocusCellForSelection(n,true),true}const s=e.getAndClearShouldCheckSelectionForTable();if(s&&Fr(r)&&Fr(o)&&o.isCollapsed()){const e=Bs(s),t=o.anchor.getNode(),r=e.getFirstChild(),l=un(t);if(null!==l&&De$1(r)){const t=r.getFirstChild();if(We$1(t)&&e.is(dl(l,n=>n.is(e)||n.is(t))))return t.selectStart(),true}}Ot(o)&&function(e,t){const n=Ht(e),o=Zr();if(!t.is(o))return;const r=Bs(t.tableKey),l=Js(n);if(l&&l.anchorNode&&l.focusNode){const n=Go(l.focusNode),o=n&&!r.isParentOf(n),s=Go(l.anchorNode),i=s&&r.isParentOf(s);if(o&&i&&l.rangeCount>0){const n=Gr(l,e);n&&(n.anchor.set(r.getKey(),t.isBackward()?r.getChildrenSize():0,"element"),l.removeAllRanges(),es(n));}}}(t,o),Fr(o)&&function(e,t){const n=Zr(),{anchor:o,focus:r}=e,l=o.getNode(),s=r.getNode(),i=un(l),c=un(s),a=i?hn(i):null,u=c?hn(c):null,h=e.isBackward(),d=i&&c&&a&&u&&a.is(u),f=u&&(!a||a.isParentOf(u)),g=a&&(!u||u.isParentOf(a));if(f){const t=e.clone(),[n]=wt(u,c,c),o=n[0][0].cell,r=n[n.length-1].at(-1).cell;t.focus.set(h?o.getKey():r.getKey(),h?0:r.getChildrenSize(),"element"),es(t);}else if(g){const t=e.clone(),[n]=wt(a,i,i),o=n[0][0].cell,r=n[n.length-1].at(-1).cell;t.anchor.set(h?r.getKey():o.getKey(),h?r.getChildrenSize():0,"element"),es(t);}else if(d){const o=t.observers.get(a.getKey());o||Le$1(335,a.getKey());const[r]=o;if(i.is(c)||(r.$setAnchorCellForSelection(Cn(r,i)),r.$setFocusCellForSelection(Cn(r,c),true)),"touch"===r.pointerType&&r.isSelecting&&e.isCollapsed()&&Fr(n)&&n.isCollapsed()){const e=un(n.anchor.getNode());e&&!e.is(c)&&(r.$setAnchorCellForSelection(Cn(r,e)),r.$setFocusCellForSelection(Cn(r,c),true),r.pointerType=null);}}}(o,e);const i=Array.from(e.observers.entries()).map(([e,[t]])=>({tableNode:Bs(e),tableObserver:t}));for(const{tableNode:e,tableObserver:n}of i)Yt(t,e,n);return false}function Yt(e,t,n){const o=Qr(),r=Zr();o&&!o.is(r)&&(Ot(o)||Ot(r))&&n.tableSelection&&!n.tableSelection.is(r)&&(Ot(o)&&o.tableKey===n.tableNodeKey?n.$updateTableTableSelection(o):!Ot(o)&&Ot(r)&&r.tableKey===n.tableNodeKey&&n.$updateTableTableSelection(null)),n.hasHijackedSelectionStyles&&!t.isSelected()?function(e,t){t.$enableHighlightStyle(),Zt(t.table,t=>{const n=t.elem;t.highlighted=false,an(e,t),n.getAttribute("style")||n.removeAttribute("style");});}(e,n):!n.hasHijackedSelectionStyles&&t.isSelected()&&function(e,t){t.$disableHighlightStyle(),Zt(t.table,t=>{t.highlighted=true,cn(e,t);});}(e,n);}function qt(e){return e[Wt]||null}function jt(e){let t=e;for(;null!=t;){const e=t.nodeName;if("TD"===e||"TH"===e){const e=t._cell;return void 0===e?null:e}t=t.parentNode;}return null}function Vt(e,t){if(!e.contains(t))return null;let n=null;for(let o=t;null!=o;o=o.parentNode){if(o===e)return n;const t=o.nodeName;"TD"!==t&&"TH"!==t||(n=o._cell||null);}return null}function Gt(e,t){const n=[],o={columns:0,domRows:n,rows:0};let r=Lt(e,t).querySelector("tr"),l=0,s=0;for(n.length=0;null!=r;){const e=r.nodeName;if("TD"===e||"TH"===e){const e={elem:r,hasBackgroundColor:""!==r.style.backgroundColor,highlighted:false,x:l,y:s};r._cell=e;let t=n[s];void 0===t&&(t=n[s]=[]),t[l]=e;}else {const e=r.firstChild;if(null!=e){r=e;continue}}const t=r.nextSibling;if(null!=t){l++,r=t;continue}const o=r.parentNode;if(null!=o){const e=o.nextSibling;if(null==e)break;s++,l=0,r=e;}}return o.columns=l+1,o.rows=s+1,o}function Qt(e,t,n){const o=new Set(n?n.getNodes():[]);Zt(t,(t,n)=>{const r=t.elem;o.has(n)?(t.highlighted=true,cn(e,t)):(t.highlighted=false,an(e,t),r.getAttribute("style")||r.removeAttribute("style"));});}function Zt(e,t){const{domRows:n}=e;for(let e=0;e<n.length;e++){const o=n[e];if(o)for(let n=0;n<o.length;n++){const r=o[n];if(!r)continue;const l=Go(r.elem);null!==l&&t(r,l,{x:n,y:e});}}}const en=(e,t,n,o,r)=>{const l="forward"===r;switch(r){case "backward":case "forward":return n!==(l?e.table.columns-1:0)?sn(t.getCellNodeFromCordsOrThrow(n+(l?1:-1),o,e.table),l):o!==(l?e.table.rows-1:0)?sn(t.getCellNodeFromCordsOrThrow(l?0:e.table.columns-1,o+(l?1:-1),e.table),l):l?t.selectNext():t.selectPrevious(),true;case "up":return 0!==o?sn(t.getCellNodeFromCordsOrThrow(n,o-1,e.table),false):t.selectPrevious(),true;case "down":return o!==e.table.rows-1?sn(t.getCellNodeFromCordsOrThrow(n,o+1,e.table),true):t.selectNext(),true;default:return false}};function tn(e,t){let n,o;if(t.startColumn===e.minColumn)n="minColumn";else {if(t.startColumn+t.cell.__colSpan-1!==e.maxColumn)return null;n="maxColumn";}if(t.startRow===e.minRow)o="minRow";else {if(t.startRow+t.cell.__rowSpan-1!==e.maxRow)return null;o="maxRow";}return [n,o]}function nn([e,t]){return ["minColumn"===e?"maxColumn":"minColumn","minRow"===t?"maxRow":"minRow"]}function on(e,t,[n,o]){const r=t[o],l=e[r];void 0===l&&Le$1(250,o,String(r));const s=t[n],i=l[s];return void 0===i&&Le$1(250,n,String(s)),i}function rn(e,t,n,o,r){const l=Nt(t,n,o),s=function(e,t){const{minColumn:n,maxColumn:o,minRow:r,maxRow:l}=t;let s=1,i=1,c=1,a=1;const u=e[r],h=e[l];for(let e=n;e<=o;e++)s=Math.max(s,u[e].cell.__rowSpan),a=Math.max(a,h[e].cell.__rowSpan);for(let t=r;t<=l;t++)i=Math.max(i,e[t][n].cell.__colSpan),c=Math.max(c,e[t][o].cell.__colSpan);return {bottomSpan:a,leftSpan:i,rightSpan:c,topSpan:s}}(t,l),{topSpan:i,leftSpan:c,bottomSpan:a,rightSpan:u}=s,h=function(e,t){const n=tn(e,t);return null===n&&Le$1(249,t.cell.getKey()),n}(l,n),[d,f]=nn(h);let g=l[d],m=l[f];"forward"===r?g+="maxColumn"===d?1:c:"backward"===r?g-="minColumn"===d?1:u:"down"===r?m+="maxRow"===f?1:i:"up"===r&&(m-="minRow"===f?1:a);const p=t[m];if(void 0===p)return false;const C=p[g];if(void 0===C)return false;const[_,S]=function(e,t,n){const o=Nt(e,t,n),r=tn(o,t);if(r)return [on(e,o,r),on(e,o,nn(r))];const l=tn(o,n);if(l)return [on(e,o,nn(l)),on(e,o,l)];const s=["minColumn","minRow"];return [on(e,o,s),on(e,o,nn(s))]}(t,n,C),w=Cn(e,_.cell),b=Cn(e,S.cell);return e.$setAnchorCellForSelection(w),e.$setFocusCellForSelection(b,true),true}function ln(e,t){if(Fr(e)||Ot(e)){const n=t.isParentOf(e.anchor.getNode()),o=t.isParentOf(e.focus.getNode());return n&&o}return false}function sn(e,t){t?e.selectStart():e.selectEnd();}function cn(t,n){const o=n.elem,r=t._config.theme;We$1(Go(o))||Le$1(131),mc(o,r.tableCellSelected);}function an(e,t){const n=t.elem;We$1(Go(n))||Le$1(131);const r=e._config.theme;xc(n,r.tableCellSelected);}function un(e){const t=dl(e,We$1);return We$1(t)?t:null}function hn(e){const t=dl(e,Rn);return Rn(t)?t:null}function dn(e,t,o,r,l,s,i){const c=ql(o.focus,l?"previous":"next");if(ic(c))return false;let a=c;for(const e of Rl(c).iterNodeCarets("shadowRoot")){if(!Tl(e)||!Wi(e.origin))return false;a=e;}const u=a.getParentAtCaret();if(!We$1(u))return false;const h=u,d=function(e){for(const t of Rl(e).iterNodeCarets("root")){const{origin:n}=t;if(We$1(n)){if(Nl(t))return Pl(n,e.direction)}else if(!De$1(n))break}return null}(Ol(h,a.direction)),f=dl(h,Rn);if(!f||!f.is(s))return false;const g=e.getElementByKey(h.getKey()),m=jt(g);if(!g||!m)return false;const p=xn(e,f);if(i.table=p,d)if("extend"===r){const t=jt(e.getElementByKey(d.origin.getKey()));if(!t)return false;i.$setAnchorCellForSelection(m),i.$setFocusCellForSelection(t,true);}else {const e=rc(d);Hl(o.anchor,e),Hl(o.focus,e);}else if("extend"===r)i.$setAnchorCellForSelection(m),i.$setFocusCellForSelection(m,true);else {const e=function(e){const t=Ll(e);return Nl(t)?rc(t):e}(Ol(f,c.direction));Hl(o.anchor,e),Hl(o.focus,e);}return gn(t),true}function fn(e,t,o,r,l,s){if(("up"===o||"down"===o)&&function(e){const t=e.getRootElement();if(!t)return false;return t.hasAttribute("aria-controls")&&"typeahead-menu"===t.getAttribute("aria-controls")}(e))return false;const i=Qr();if(!ln(i,r)){if(Fr(i)){if("backward"===o){if(i.focus.offset>0)return false;const e=function(e){for(let t=e,n=e;null!==n;t=n,n=n.getParent())if(Wi(n)){if(n!==t&&n.getFirstChild()!==t)return null;if(!n.isInline())return n}return null}(i.focus.getNode());if(!e)return false;const n=e.getPreviousSibling();return !!Rn(n)&&(gn(t),t.shiftKey?i.focus.set(n.getParentOrThrow().getKey(),n.getIndexWithinParent(),"element"):n.selectEnd(),true)}if(t.shiftKey&&("up"===o||"down"===o)){const e=i.focus.getNode();if(!i.isCollapsed()&&("up"===o&&!i.isBackward()||"down"===o&&i.isBackward())){let l=dl(e,e=>Rn(e));if(We$1(l)&&(l=dl(l,Rn)),l!==r)return false;if(!l)return false;const s="down"===o?l.getNextSibling():l.getPreviousSibling();if(!s)return false;let c=0;"up"===o&&Wi(s)&&(c=s.getChildrenSize());let a=s;if("up"===o&&Wi(s)){const e=s.getLastChild();a=e||s,c=Tr(a)?a.getTextContentSize():0;}const u=i.clone();return u.focus.set(a.getKey(),c,Tr(a)?"text":"element"),es(u),gn(t),true}if(Is(e)){const e="up"===o?i.getNodes()[i.getNodes().length-1]:i.getNodes()[0];if(e){if(null!==Bt(r,e)){const e=r.getFirstDescendant(),t=r.getLastDescendant();if(!e||!t)return false;const[n]=yt(e),[o]=yt(t),s=r.getCordsFromCellNode(n,l.table),i=r.getCordsFromCellNode(o,l.table),c=r.getDOMCellFromCordsOrThrow(s.x,s.y,l.table),a=r.getDOMCellFromCordsOrThrow(i.x,i.y,l.table);return l.$setAnchorCellForSelection(c),l.$setFocusCellForSelection(a,true),true}}return false}{let r=dl(e,e=>Wi(e)&&!e.isInline());if(We$1(r)&&(r=dl(r,Rn)),!r)return false;const s="down"===o?r.getNextSibling():r.getPreviousSibling();if(Rn(s)&&l.tableNodeKey===s.getKey()){const e=s.getFirstDescendant(),n=s.getLastDescendant();if(!e||!n)return false;const[r]=yt(e),[l]=yt(n),c=i.clone();return c.focus.set(("up"===o?r:l).getKey(),"up"===o?0:l.getChildrenSize(),"element"),gn(t),es(c),true}}}}return "down"===o&&yn(e)&&s.setShouldCheckSelectionForTable(r.getKey()),false}if(Fr(i)){if("backward"===o||"forward"===o){return dn(e,t,i,t.shiftKey?"extend":"move","backward"===o,r,l)}if(i.isCollapsed()){const{anchor:c,focus:a}=i,u=dl(c.getNode(),We$1),h=dl(a.getNode(),We$1);if(!We$1(u)||!u.is(h))return false;const d=hn(u);if(d!==r&&null!=d){const n=Lt(d,e.getElementByKey(d.getKey()));if(null!=n)return l.table=Gt(d,n),fn(e,t,o,d,l,s)}const f=e.getElementByKey(u.__key),g=e.getElementByKey(c.key);if(null==g||null==f)return false;let m;if("element"===c.type)m=g.getBoundingClientRect();else {const t=Js(Ht(e));if(null===t||0===t.rangeCount)return false;m=t.getRangeAt(0).getBoundingClientRect();}const p="up"===o?u.getFirstChild():u.getLastChild();if(null==p)return false;const C=e.getElementByKey(p.__key);if(null==C)return false;const _=C.getBoundingClientRect();if("up"===o?_.top>m.top-m.height:m.bottom+m.height>_.bottom){gn(t);const e=r.getCordsFromCellNode(u,l.table);if(!t.shiftKey)return en(l,r,e.x,e.y,o);{const t=r.getDOMCellFromCordsOrThrow(e.x,e.y,l.table);l.$setAnchorCellForSelection(t),l.$setFocusCellForSelection(t,true);}return true}}}else if(Ot(i)){const{anchor:s,focus:c}=i,a=dl(s.getNode(),We$1),u=dl(c.getNode(),We$1),[h]=i.getNodes();Rn(h)||Le$1(251);const d=Lt(h,e.getElementByKey(h.getKey()));if(!We$1(a)||!We$1(u)||!Rn(h)||null==d)return false;l.$updateTableTableSelection(i);const f=Gt(h,d),g=r.getCordsFromCellNode(a,f),m=r.getDOMCellFromCordsOrThrow(g.x,g.y,f);if(l.$setAnchorCellForSelection(m),gn(t),t.shiftKey){const[e,t,n]=wt(r,a,u);return rn(l,e,t,n,o)}return u.selectEnd(),true}return false}function gn(e){e.preventDefault(),e.stopImmediatePropagation(),e.stopPropagation();}function mn(e,t,n){const o=eo();"first"===e?t.insertBefore(o):t.insertAfter(o),o.append(...n||[]),o.selectEnd();}function pn(e,t,o){const r=o.getParent();if(!r)return;const l=Js(Ht(e));if(!l)return;const s=l.anchorNode,i=e.getElementByKey(r.getKey()),c=Lt(o,e.getElementByKey(o.getKey()));if(!s||!i||!c||!i.contains(s)||c.contains(s))return;const a=dl(t.anchor.getNode(),e=>We$1(e));if(!a)return;const u=dl(a,e=>Rn(e));if(!Rn(u)||!u.is(o))return;const[h,d]=wt(o,a,a),f=h[0][0],g=h[h.length-1][h[0].length-1],{startRow:m,startColumn:p}=d,C=m===f.startRow&&p===f.startColumn,_=m===g.startRow&&p===g.startColumn;return C?"first":_?"last":void 0}function Cn(e,t){const{tableNode:n}=e.$lookup(),o=n.getCordsFromCellNode(t,e.table);return n.getDOMCellFromCordsOrThrow(o.x,o.y,e.table)}function _n(e,t,n){return Bt(e,Go(t,n))}function Sn(e,t,n){const o=e.querySelector("colgroup");if(!o)return;const r=[];for(let e=0;e<t;e++){const t=document.createElement("col"),o=n&&n[e];o&&(t.style.width=`${o}px`),r.push(t);}o.replaceChildren(...r);}function wn(t,n,r){if(!n.theme.tableAlignment)return;const l=[],s=[];for(const e of ["center","right"]){const t=n.theme.tableAlignment[e];t&&(e===r?s:l).push(t);}xc(t,...l),mc(t,...s);}const bn=new WeakSet;function yn(e=Zs()){return bn.has(e)}function Nn(e,t){bn.add(e);}class vn extends Bi{__rowStriping;__frozenColumnCount;__frozenRowCount;__colWidths;static getType(){return "table"}getColWidths(){return this.getLatest().__colWidths}setColWidths(e){const t=this.getWritable();return t.__colWidths=e,t}static clone(e){return new vn(e.__key)}afterCloneFrom(e){super.afterCloneFrom(e),this.__colWidths=e.__colWidths,this.__rowStriping=e.__rowStriping,this.__frozenColumnCount=e.__frozenColumnCount,this.__frozenRowCount=e.__frozenRowCount;}static importDOM(){return {table:e=>({conversion:Tn,priority:1})}}static importJSON(e){return Fn().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setRowStriping(e.rowStriping||false).setFrozenColumns(e.frozenColumnCount||0).setFrozenRows(e.frozenRowCount||0).setColWidths(e.colWidths)}constructor(e){super(e),this.__rowStriping=false,this.__frozenColumnCount=0,this.__frozenRowCount=0,this.__colWidths=void 0;}exportJSON(){return {...super.exportJSON(),colWidths:this.getColWidths(),frozenColumnCount:this.__frozenColumnCount?this.__frozenColumnCount:void 0,frozenRowCount:this.__frozenRowCount?this.__frozenRowCount:void 0,rowStriping:this.__rowStriping?this.__rowStriping:void 0}}extractWithChild(e,t,n){return "html"===n}getDOMSlot(e){const t=zt(e)?e:e.querySelector("table");return zt(t)||Le$1(229),super.getDOMSlot(e).withElement(t).withAfter(t.querySelector("colgroup"))}createDOM(t,n){const o=document.createElement("table");this.__style&&nr(o.style,this.__style);const r=document.createElement("colgroup");if(o.appendChild(r),ll(r),mc(o,t.theme.table),this.updateTableElement(null,o,t),yn(n)){const n=document.createElement("div"),r=t.theme.tableScrollableWrapper;return r?mc(n,r):n.style.overflowX="auto",n.appendChild(o),this.updateTableWrapper(null,n,o,t),n}return o}updateTableWrapper(t,n,r,l){this.__frozenColumnCount!==(t?t.__frozenColumnCount:0)&&function(t,n,r,l){l>0?(mc(t,r.theme.tableFrozenColumn),n.setAttribute("data-lexical-frozen-column","true")):(xc(t,r.theme.tableFrozenColumn),n.removeAttribute("data-lexical-frozen-column"));}(n,r,l,this.__frozenColumnCount),this.__frozenRowCount!==(t?t.__frozenRowCount:0)&&function(t,n,r,l){l>0?(mc(t,r.theme.tableFrozenRow),n.setAttribute("data-lexical-frozen-row","true")):(xc(t,r.theme.tableFrozenRow),n.removeAttribute("data-lexical-frozen-row"));}(n,r,l,this.__frozenRowCount);}updateTableElement(t,n,r){this.__style!==(t?t.__style:"")&&nr(n.style,this.__style,t?t.__style:""),this.__rowStriping!==(!!t&&t.__rowStriping)&&function(t,n,r){r?(mc(t,n.theme.tableRowStriping),t.setAttribute("data-lexical-row-striping","true")):(xc(t,n.theme.tableRowStriping),t.removeAttribute("data-lexical-row-striping"));}(n,r,this.__rowStriping);const l=t?t.getColumnCount():0,s=t?t.__colWidths:void 0;this.getColumnCount()===l&&this.getColWidths()===s||Sn(n,this.getColumnCount(),this.getColWidths()),wn(n,r,this.getFormatType());}updateDOM(e,t,n){const o=Lt(this,t);return t===o===yn()||(Ys(r=t)&&"DIV"===r.nodeName&&this.updateTableWrapper(e,t,o,n),this.updateTableElement(e,o,n),false);var r;}scaleDOMColWidths(e,t){const n=this.getColWidths();if(!n)return;Sn(Lt(this,e),this.getColumnCount(),n.map(e=>e*t));}exportDOM(e){const t=super.exportDOM(e),{element:n}=t;return {after:n=>{if(t.after&&(n=t.after(n)),!zt(n)&&Ys(n)&&(n=n.querySelector("table")),!zt(n))return null;wn(n,e._config,this.getFormatType());const[o]=bt(this,null,null),r=new Map;for(const e of o)for(const t of e){const e=t.cell.getKey();r.has(e)||r.set(e,{colSpan:t.cell.getColSpan(),startColumn:t.startColumn});}const s=new Set;for(const e of n.querySelectorAll(":scope > tr > [data-temporary-table-cell-lexical-key]")){const t=e.getAttribute("data-temporary-table-cell-lexical-key");if(t){const n=r.get(t);if(e.removeAttribute("data-temporary-table-cell-lexical-key"),n){r.delete(t);for(let e=0;e<n.colSpan;e++)s.add(e+n.startColumn);}}}const i=n.querySelector(":scope > colgroup");if(i){const e=Array.from(n.querySelectorAll(":scope > colgroup > col")).filter((e,t)=>s.has(t));i.replaceChildren(...e);}const c=n.querySelectorAll(":scope > tr");if(c.length>0){const e=document.createElement("tbody");for(const t of c)e.appendChild(t);n.append(e);}return n},element:!zt(n)&&Ys(n)?n.querySelector("table"):n}}canBeEmpty(){return false}isShadowRoot(){return true}getCordsFromCellNode(e,t){const{rows:n,domRows:o}=t;for(let t=0;t<n;t++){const n=o[t];if(null!=n)for(let o=0;o<n.length;o++){const r=n[o];if(null==r)continue;const{elem:l}=r,s=_n(this,l);if(null!==s&&e.is(s))return {x:o,y:t}}}throw new Error("Cell not found in table.")}getDOMCellFromCords(e,t,n){const{domRows:o}=n,r=o[t];if(null==r)return null;const l=r[e<r.length?e:r.length-1];return null==l?null:l}getDOMCellFromCordsOrThrow(e,t,n){const o=this.getDOMCellFromCords(e,t,n);if(!o)throw new Error("Cell not found at cords.");return o}getCellNodeFromCords(e,t,n){const o=this.getDOMCellFromCords(e,t,n);if(null==o)return null;const r=Go(o.elem);return We$1(r)?r:null}getCellNodeFromCordsOrThrow(e,t,n){const o=this.getCellNodeFromCords(e,t,n);if(!o)throw new Error("Node at cords not TableCellNode.");return o}getRowStriping(){return Boolean(this.getLatest().__rowStriping)}setRowStriping(e){const t=this.getWritable();return t.__rowStriping=e,t}setFrozenColumns(e){const t=this.getWritable();return t.__frozenColumnCount=e,t}getFrozenColumns(){return this.getLatest().__frozenColumnCount}setFrozenRows(e){const t=this.getWritable();return t.__frozenRowCount=e,t}getFrozenRows(){return this.getLatest().__frozenRowCount}canSelectBefore(){return true}canIndent(){return false}getColumnCount(){const e=this.getFirstChild();if(!e)return 0;let t=0;return e.getChildren().forEach(e=>{We$1(e)&&(t+=e.getColSpan());}),t}}function xn(e,t){const n=e.getElementByKey(t.getKey());return null===n&&Le$1(230),Gt(t,n)}function Tn(e){const n=Fn();e.hasAttribute("data-lexical-row-striping")&&n.setRowStriping(true),e.hasAttribute("data-lexical-frozen-column")&&n.setFrozenColumns(1),e.hasAttribute("data-lexical-frozen-row")&&n.setFrozenRows(1);const o=e.querySelector(":scope > colgroup");if(o){let e=[];for(const t of o.querySelectorAll(":scope > col")){let n=t.style.width||"";if(!Ke$1.test(n)&&(n=t.getAttribute("width")||"",!/^\d+$/.test(n))){e=void 0;break}e.push(parseFloat(n));}e&&n.setColWidths(e);}return {after:e=>Ht$3(e,De$1),node:n}}function Fn(){return zs(new vn)}function Rn(e){return e instanceof vn}function On(e){De$1(e.getParent())?e.isEmpty()&&e.append(eo()):e.remove();}function Kn(e){Rn(e.getParent())?Ot$3(e,We$1):e.remove();}function An(e){Ot$3(e,De$1);const[t]=bt(e,null,null),n=t.reduce((e,t)=>Math.max(e,t.length),0),o=e.getChildren();for(let e=0;e<t.length;++e){const r=o[e];if(!r)continue;De$1(r)||Le$1(254,r.constructor.name,r.getType());const l=t[e].reduce((e,t)=>t?1+e:e,0);if(l!==n)for(let e=l;e<n;++e){const e=$e$1();e.append(eo()),r.append(e);}}const r=e.getColWidths(),l=e.getColumnCount();if(r&&r.length!==l){let t;if(l<r.length)t=r.slice(0,l);else if(r.length>0){const e=r[r.length-1];t=[...r,...Array(l-r.length).fill(e)];}e.setColWidths(t);}}function En(e){if(e.detail<3||!qs(e.target))return false;const t=Go(e.target);if(null===t)return false;const o=dl(t,e=>Wi(e)&&!e.isInline());if(null===o)return false;return !!We$1(o.getParent())&&(o.select(0),true)}function kn(){const e=Qr();if(!Fr(e))return false;const t=hn(e.anchor.getNode());if(null===t)return false;const n=Zo();if(!n.is(t.getParent())||1!==n.getChildrenSize())return false;const[o]=bt(t,null,null);if(0===o.length||0===o[0].length)return false;const r=o[0][0];if(!r||!r.cell)return false;const l=o[o.length-1],s=l[l.length-1];if(!s||!s.cell)return false;const i=At(t,r.cell,s.cell);return es(i),true}function $n(e,t=true){const n=new Mt,o=(o,r,l)=>{const s=Lt(o,l),i=Jt(o,s,e,t,n);n.observers.set(r,[i,s]);};return Cc(Ut(e,n),e.registerCommand(ie$4,()=>Xt(n,e),so),e.registerMutationListener(vn,t=>{e.getEditorState().read(()=>{for(const[e,r]of t){const t=n.observers.get(e);if("created"===r||"updated"===r){const{tableNode:r,tableElement:l}=kt(e);void 0===t?o(r,e,l):l!==t[1]&&(t[0].removeListeners(),n.observers.delete(e),o(r,e,l));}else "destroyed"===r&&void 0!==t&&(t[0].removeListeners(),n.observers.delete(e));}},{editor:e});},{skipInitialization:false}),()=>{for(const[,[e]]of n.observers)e.removeListeners();})}function Wn(e,t){e.hasNodes([vn])||Le$1(255);const{hasNestedTables:o=ft$1(false)}={};return Cc(e.registerCommand(ze$1,e=>function({rows:e,columns:t,includeHeaders:n},o){const r=Qr()||Zr();if(!r||!Fr(r))return false;if(!o&&hn(r.anchor.getNode()))return false;const l=Xe$1(Number(e),Number(t),n);Pt$3(l);const s=l.getFirstDescendant();return Tr(s)&&s.select(),true}(e,o.peek()),ro),e.registerCommand(oe$6,(t,r)=>e===r&&function(e,t){const{nodes:o,selection:r}=e;if(!o.some(e=>Rn(e)||pt$2(e).some(e=>Rn(e.node))))return false;const l=Ot(r),s=Fr(r);if(!(s&&null!==dl(r.anchor.getNode(),e=>We$1(e))&&null!==dl(r.focus.getNode(),e=>We$1(e))||l))return false;if(1===o.length&&Rn(o[0]))return function(e,t){const o=t.getStartEndPoints(),r=Ot(t);if(null===o)return false;const[l,s]=o,[i,c,a]=yt(l),u=dl(s.getNode(),e=>We$1(e));if(!(We$1(i)&&We$1(u)&&De$1(c)&&Rn(a)))return false;const[h,d,f]=wt(a,i,u),[m]=bt(e,null,null),C=h.length,_=C>0?h[0].length:0;let S=d.startRow,w=d.startColumn,b=m.length,y=b>0?m[0].length:0;if(r){const e=Nt(h,d,f),t=e.maxRow-e.minRow+1,n=e.maxColumn-e.minColumn+1;S=e.minRow,w=e.minColumn,b=Math.min(b,t),y=Math.min(y,n);}let N=false;const v=Math.min(C,S+b)-1,x=Math.min(_,w+y)-1,T=new Set;for(let e=S;e<=v;e++)for(let t=w;t<=x;t++){const n=h[e][t];T.has(n.cell.getKey())||(1===n.cell.__rowSpan&&1===n.cell.__colSpan||(St(n.cell),T.add(n.cell.getKey()),N=true));}let[F]=bt(a.getWritable(),null,null);const R=b-C+S;for(let e=0;e<R;e++){rt(F[C-1][0].cell);}const O=y-_+w;for(let e=0;e<O;e++){ct(F[0][_-1].cell,true,false);}[F]=bt(a.getWritable(),null,null);for(let e=S;e<S+b;e++)for(let t=w;t<w+y;t++){const n=e-S,o=t-w,r=m[n][o];if(r.startRow!==n||r.startColumn!==o)continue;const l=r.cell;if(1!==l.__rowSpan||1!==l.__colSpan){const n=[],o=Math.min(e+l.__rowSpan,S+b)-1,r=Math.min(t+l.__colSpan,w+y)-1;for(let l=e;l<=o;l++)for(let e=t;e<=r;e++){const t=F[l][e];n.push(t.cell);}pt(n),N=true;}const{cell:s}=F[e][t],i=l.getBackgroundColor();null!=i&&s.setBackgroundColor(i);const c=s.getChildren();l.getChildren().forEach(e=>{if(Tr(e)){eo().append(e),s.append(e);}else s.append(e);}),c.forEach(e=>e.remove());}if(r&&N){const[e]=bt(a.getWritable(),null,null);e[d.startRow][d.startColumn].cell.selectEnd();}return true}(o[0],r);if(s&&t.peek()&&!function(e){if(Ot(e)&&!e.focus.getNode().is(e.anchor.getNode()))return true;if(Fr(e)&&We$1(e.anchor.getNode())&&!e.anchor.getNode().is(e.focus.getNode()))return true;return false}(r))return false;return true}(t,o),ro),e.registerCommand(Ue$2,kn,io),e.registerCommand(se$5,En,ro),e.registerNodeTransform(vn,An),e.registerNodeTransform(He$1,Kn),e.registerNodeTransform(Ee$1,On))}
11536
+ static #isGalleryElement(element) {
11537
+ const attachmentChildren = element.querySelectorAll(`:scope > :is(${this.#attachmentTags.join()})`);
11538
+ return element.textContent.trim() === ""
11539
+ && attachmentChildren.length > 0
11540
+ && element.children.length === attachmentChildren.length
11541
+ }
11204
11542
 
11205
- // Partition a stretch of text into consecutive { start, end, range } segments,
11206
- // where offsets are relative to the text and range is the covering source
11207
- // range — expressed in outer coordinates as { start, end, ... } — or null for
11208
- // the stretches no range covers. Ranges must be sorted and non-overlapping.
11209
- function segmentTextByRanges(text, textStart, ranges) {
11210
- const segments = [];
11211
- let cursor = 0;
11543
+ static get #attachmentTags() {
11544
+ return Object.keys(ActionTextAttachmentNode.importDOM())
11545
+ }
11212
11546
 
11213
- for (const range of ranges) {
11214
- const from = Math.max(range.start - textStart, cursor);
11215
- const to = Math.min(range.end - textStart, text.length);
11547
+ createDOM() {
11548
+ const div = document.createElement("div");
11549
+ div.className = this.#galleryClassNames;
11550
+ return div
11551
+ }
11216
11552
 
11217
- if (from < to) {
11218
- if (from > cursor) {
11219
- segments.push({ start: cursor, end: from, range: null });
11220
- }
11221
- segments.push({ start: from, end: to, range });
11222
- cursor = to;
11553
+ updateDOM(_prevNode, dom) {
11554
+ dom.className = this.#galleryClassNames;
11555
+ return false
11556
+ }
11557
+
11558
+ canBeEmpty() {
11559
+ // Return `true` to conform to `$isBlock(node)`
11560
+ // We clean-up empty galleries with a transform
11561
+ return true
11562
+ }
11563
+
11564
+ collapseAtStart(_selection) {
11565
+ return true
11566
+ }
11567
+
11568
+ insertNewAfter(selection, restoreSelection) {
11569
+ const selectionBeforeLastChild = selection.anchor.getNode().is(this) && selection.anchor.offset == this.getChildrenSize() - 1;
11570
+ if (selectionBeforeLastChild) {
11571
+ const paragraph = eo();
11572
+ this.insertAfter(paragraph, false);
11573
+ paragraph.insertAfter(this.getLastChild(), false);
11574
+ paragraph.selectEnd();
11575
+
11576
+ // return null as selection has been managed
11577
+ return null
11223
11578
  }
11579
+
11580
+ const newNode = $createImageGalleryNode();
11581
+ this.insertAfter(newNode, restoreSelection);
11582
+ return newNode
11224
11583
  }
11225
11584
 
11226
- if (cursor < text.length) {
11227
- segments.push({ start: cursor, end: text.length, range: null });
11585
+ getImageAttachments() {
11586
+ const children = this.getChildren();
11587
+ return children.filter($isActionTextAttachmentNode)
11228
11588
  }
11229
11589
 
11230
- return segments
11231
- }
11590
+ exportDOM() {
11591
+ const div = document.createElement("div");
11592
+ div.className = this.#galleryClassNames;
11593
+ return { element: div }
11594
+ }
11232
11595
 
11233
- // Shared, strictly-contained element used to attach ephemeral nodes when we
11234
- // need to read computed styles (e.g. canonicalizing style values, resolving
11235
- // CSS custom properties). The container is created once and attached to
11236
- // `document.body` once; subsequent child mutations happen *inside* the
11237
- // contained subtree so they do not invalidate style on the rest of the page.
11238
- //
11239
- // Without this, `document.body.appendChild(...)` / `element.remove()` calls
11240
- // forced the browser to re-evaluate every ancestor-dependent selector (`:has()`,
11241
- // descendant combinators, universal sibling rules) across the document on each
11242
- // invocation — a 13,000+ element style recalc per call on a typical Basecamp
11243
- // page.
11596
+ collapseWith(node, backwards) {
11597
+ if (!ImageGalleryNode.canCollapseWith(node)) return false
11244
11598
 
11245
- let resolverRoot = null;
11599
+ if (backwards) {
11600
+ $t$2(this, node);
11601
+ } else {
11602
+ this.append(node);
11603
+ }
11246
11604
 
11247
- function styleResolverRoot() {
11248
- if (resolverRoot && resolverRoot.isConnected) return resolverRoot
11605
+ Ot$3(this, ImageGalleryNode.isValidChild);
11249
11606
 
11250
- resolverRoot = document.createElement("div");
11251
- resolverRoot.setAttribute("aria-hidden", "true");
11252
- resolverRoot.setAttribute("data-lexxy-style-resolver", "");
11253
- // `contain: strict` (size, layout, paint, style) isolates everything.
11254
- // The root itself paints nothing (visibility hidden), has zero
11255
- // geometric impact (position fixed, intrinsic size via contain), and
11256
- // never leaks style invalidation to its ancestors.
11257
- resolverRoot.style.cssText = "contain: strict; position: fixed; top: 0; left: 0; visibility: hidden; pointer-events: none; width: 0; height: 0;";
11258
- document.body.appendChild(resolverRoot);
11259
- return resolverRoot
11260
- }
11607
+ return true
11608
+ }
11261
11609
 
11262
- function isSelectionHighlighted(selection) {
11263
- if (!Fr(selection)) return false
11610
+ unwrapEmptyNode() {
11611
+ if (this.isEmpty()) {
11612
+ const paragraph = eo();
11613
+ return this.replace(paragraph)
11614
+ }
11615
+ }
11264
11616
 
11265
- if (selection.isCollapsed()) {
11266
- return hasHighlightStyles(selection.style)
11267
- } else {
11268
- return selection.hasFormat("highlight")
11617
+ replaceWithSingularChild() {
11618
+ if (this.#hasSingularChild) {
11619
+ const child = this.getFirstChild();
11620
+ return this.replace($makeSafeForRoot(child))
11621
+ }
11269
11622
  }
11270
- }
11271
11623
 
11272
- function getHighlightStyles(selection) {
11273
- if (!Fr(selection)) return null
11624
+ splitAroundInvalidChild() {
11625
+ for (const child of jt$2(this)) {
11626
+ if (ImageGalleryNode.isValidChild(child)) continue
11274
11627
 
11275
- let styles = oe$5(selection.style);
11276
- if (!styles.color && !styles["background-color"]) {
11277
- const anchorNode = selection.anchor.getNode();
11278
- if (Tr(anchorNode)) {
11279
- styles = oe$5(anchorNode.getStyle());
11628
+ const poppedNode = $makeSafeForRoot(child);
11629
+ const [ topGallery, secondGallery ] = this.splitAtIndex(poppedNode.getIndexWithinParent());
11630
+ topGallery.insertAfter(poppedNode);
11631
+ poppedNode.selectEnd();
11632
+
11633
+ // remove an empty gallery rather than let it unwrap to a paragraph
11634
+ if (secondGallery.isEmpty()) secondGallery.remove();
11635
+
11636
+ break
11280
11637
  }
11281
11638
  }
11282
11639
 
11283
- const color = styles.color || null;
11284
- const backgroundColor = styles["background-color"] || null;
11285
- if (!color && !backgroundColor) return null
11640
+ splitAtIndex(index) {
11641
+ return Us(this, index)
11642
+ }
11286
11643
 
11287
- return { color, backgroundColor }
11644
+ get #hasSingularChild() {
11645
+ return this.getChildrenSize() === 1
11646
+ }
11647
+
11648
+ get #galleryClassNames() {
11649
+ return `attachment-gallery attachment-gallery--${this.getChildrenSize()}`
11650
+ }
11288
11651
  }
11289
11652
 
11290
- function hasHighlightStyles(cssOrStyles) {
11291
- const styles = typeof cssOrStyles === "string" ? oe$5(cssOrStyles) : cssOrStyles;
11292
- return !!(styles.color || styles["background-color"])
11653
+ function $createImageGalleryNode() {
11654
+ return new ImageGalleryNode()
11293
11655
  }
11294
11656
 
11295
- function applyCanonicalizers(styles, canonicalizers = []) {
11296
- return canonicalizers.reduce((css, canonicalizer) => {
11297
- return canonicalizer.applyCanonicalization(css)
11298
- }, styles)
11657
+ function $isImageGalleryNode(node) {
11658
+ return node instanceof ImageGalleryNode
11299
11659
  }
11300
11660
 
11301
- class StyleCanonicalizer {
11302
- constructor(property, allowedValues= []) {
11303
- this._property = property;
11304
- this._allowedValues = allowedValues;
11305
- this._canonicalValues = this.#allowedValuesIdentityObject;
11661
+ function $findOrCreateGalleryForImage(node) {
11662
+ if (!ImageGalleryNode.canCollapseWith(node)) return null
11663
+
11664
+ const existingGallery = At$2(node, ImageGalleryNode);
11665
+ return existingGallery ?? Tt$4(node, $createImageGalleryNode)
11666
+ }
11667
+
11668
+ class CaptionEditor {
11669
+ #editorElement
11670
+ #editor
11671
+ #input = createElement("textarea", { className: "lexxy-caption-editor", hidden: true, tabIndex: -1, rows: 1, placeholder: "Add caption..." })
11672
+ #nodeKey
11673
+ #caption
11674
+ #listeners = new ListenerBin()
11675
+ #resizeObserver = new ResizeObserver(() => this.#updatePosition())
11676
+
11677
+ constructor(editorElement) {
11678
+ this.#editorElement = editorElement;
11679
+ this.#editor = editorElement.editor;
11680
+ editorElement.append(this.#input);
11681
+ this.#listeners.track(
11682
+ registerEventListener(this.#input, "blur", () => this.#save()),
11683
+ registerEventListener(this.#input, "keydown", event => this.#handleKeydown(event)),
11684
+ registerEventListener(this.#input, "input", () => this.#updatePosition()),
11685
+ registerEventListener(editorElement, "scroll", () => this.#updatePosition(), { capture: true, passive: true }),
11686
+ this.#editor.registerUpdateListener(() => this.#checkAttachment())
11687
+ );
11306
11688
  }
11307
11689
 
11308
- applyCanonicalization(css) {
11309
- const styles = { ...oe$5(css) };
11690
+ dispose() {
11691
+ this.#listeners.dispose();
11692
+ this.#close();
11693
+ this.#input.remove();
11694
+ }
11310
11695
 
11311
- styles[this._property] = this.getCanonicalAllowedValue(styles[this._property]);
11312
- if (!styles[this._property]) {
11313
- delete styles[this._property];
11696
+ open(nodeKey) {
11697
+ const caption = this.#editor.getElementByKey(nodeKey)?.querySelector("figcaption.attachment__caption--editable");
11698
+ if (caption) {
11699
+ if (this.#nodeKey !== nodeKey) {
11700
+ this.#edit(nodeKey, caption);
11701
+ }
11702
+ return true
11703
+ } else {
11704
+ return false
11314
11705
  }
11706
+ }
11315
11707
 
11316
- return F$6(styles)
11708
+ #save() {
11709
+ if (this.#nodeKey) {
11710
+ const key = this.#nodeKey;
11711
+ const value = this.#input.value;
11712
+ this.#close();
11713
+ this.#editor.update(() => {
11714
+ const node = Yo(key);
11715
+ if (node && node.caption !== value) node.getWritable().caption = value;
11716
+ }, { tag: qn, discrete: true });
11717
+ }
11317
11718
  }
11318
11719
 
11319
- getCanonicalAllowedValue(value) {
11320
- return this._canonicalValues[value] ||= this.#resolveCannonicalValue(value)
11720
+ #close() {
11721
+ this.#nodeKey = null;
11722
+ this.#resizeObserver.disconnect();
11723
+ if (this.#caption) {
11724
+ this.#caption.classList.remove("attachment__caption--editing");
11725
+ this.#caption.style.removeProperty("min-height");
11726
+ this.#caption = null;
11727
+ }
11728
+ this.#input.hidden = true;
11321
11729
  }
11322
11730
 
11323
- // Private
11731
+ #handleKeydown(event) {
11732
+ if (!event.isComposing && [ "Enter", "Escape" ].includes(event.key)) {
11733
+ event.preventDefault();
11734
+ const key = this.#nodeKey;
11735
+ this.#input.blur();
11736
+ this.#editor.getRootElement()?.focus({ preventScroll: true });
11737
+ this.#editor.update(() => {
11738
+ const node = Yo(key);
11739
+ if (node) {
11740
+ if (event.key === "Enter") {
11741
+ if ($isImageGalleryNode(node.getParent()) && !node.getNextSibling()) {
11742
+ node.getParent().selectNext(0, 0);
11743
+ } else {
11744
+ node.selectNext(0, 0);
11745
+ }
11746
+ } else {
11747
+ es($createNodeSelectionWith(node));
11748
+ }
11749
+ }
11750
+ }, { tag: Jn });
11751
+ }
11752
+ event.stopPropagation();
11753
+ }
11324
11754
 
11325
- get #allowedValuesIdentityObject() {
11326
- return this._allowedValues.reduce((object, value) => ({ ...object, [value]: value }), {})
11755
+ #updatePosition() {
11756
+ if (this.#caption?.isConnected) {
11757
+ const rect = this.#caption.getBoundingClientRect();
11758
+ const editorRect = this.#editorElement.getBoundingClientRect();
11759
+ this.#input.style.left = `${rect.left - editorRect.left - this.#editorElement.clientLeft + this.#editorElement.scrollLeft}px`;
11760
+ this.#input.style.top = `${rect.top - editorRect.top - this.#editorElement.clientTop + this.#editorElement.scrollTop}px`;
11761
+ this.#input.style.width = `${rect.width}px`;
11762
+ this.#input.style.height = "0px";
11763
+ const height = this.#input.scrollHeight;
11764
+ this.#input.style.height = `${height}px`;
11765
+ this.#caption.style.minHeight = `${height}px`;
11766
+ }
11327
11767
  }
11328
11768
 
11329
- #resolveCannonicalValue(value) {
11330
- let index = this.#computedAllowedValues.indexOf(value);
11331
- if (index === -1) {
11332
- index = this.#computedAllowedValues.indexOf(computeStyleValues(this._property, [ value ])[0]);
11769
+ #checkAttachment() {
11770
+ if (this.#nodeKey && this.#editor.getElementByKey(this.#nodeKey)?.querySelector("figcaption") !== this.#caption) {
11771
+ this.#close();
11772
+ } else {
11773
+ this.#updatePosition();
11774
+ }
11775
+ }
11776
+
11777
+ #edit(nodeKey, caption) {
11778
+ this.#save();
11779
+ this.#nodeKey = nodeKey;
11780
+ this.#caption = caption;
11781
+ this.#editor.getEditorState().read(() => {
11782
+ const node = Yo(nodeKey);
11783
+ this.#input.value = node.caption;
11784
+ if (node.isVideo) {
11785
+ this.#input.ariaLabel = "Video caption";
11786
+ } else {
11787
+ this.#input.ariaLabel = "Image caption";
11788
+ }
11789
+ });
11790
+
11791
+ caption.scrollIntoView({ block: "nearest", inline: "nearest" });
11792
+ const style = getComputedStyle(caption);
11793
+ this.#input.style.font = style.font;
11794
+ this.#input.style.padding = style.padding;
11795
+ this.#input.style.color = style.color;
11796
+ this.#input.style.textAlign = getComputedStyle(caption.firstElementChild).textAlign;
11797
+ this.#input.hidden = false;
11798
+ caption.classList.add("attachment__caption--editing");
11799
+ this.#resizeObserver.observe(caption);
11800
+ this.#resizeObserver.observe(this.#editorElement);
11801
+ this.#updatePosition();
11802
+ this.#input.focus({ preventScroll: true });
11803
+ }
11804
+ }
11805
+
11806
+ class UploadRequests {
11807
+ #requestsByKey = new Map()
11808
+
11809
+ track(key, request) {
11810
+ this.#requestsByKey.set(key, request);
11811
+ }
11812
+
11813
+ forget(key) {
11814
+ this.#requestsByKey.delete(key);
11815
+ }
11816
+
11817
+ abort(key) {
11818
+ const request = this.#requestsByKey.get(key);
11819
+ if (request) {
11820
+ this.#requestsByKey.delete(key);
11821
+ request.abort();
11333
11822
  }
11334
- return index === -1 ? null : this._allowedValues[index]
11335
11823
  }
11336
11824
 
11337
- get #computedAllowedValues() {
11338
- return this._computedAllowedValues ||= computeStyleValues(this._property, this._allowedValues)
11825
+ clear() {
11826
+ this.#requestsByKey.clear();
11339
11827
  }
11340
11828
  }
11341
11829
 
11342
- // Separates DOM writes from layout reads to avoid forced reflows, and attaches
11343
- // resolver elements to a strictly-contained root (outside the normal document
11344
- // flow) so neither the attach nor the detach invalidate styles on the rest of
11345
- // the page. Without containment, appending to `document.body` triggered a
11346
- // page-wide style recalc on every canonicalization pass.
11347
- function computeStyleValues(property, values) {
11348
- const fragment = document.createDocumentFragment();
11830
+ /**
11831
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
11832
+ *
11833
+ * This source code is licensed under the MIT license found in the
11834
+ * LICENSE file in the root directory of this source tree.
11835
+ *
11836
+ */
11349
11837
 
11350
- const elements = values.map(value => {
11351
- const element = createElement("span", { style: `display: none; ${property}: ${value};` });
11352
- fragment.appendChild(element);
11353
- return element
11354
- });
11838
+ const Ke$1=/^(\d+(?:\.\d+)?)px$/,Ae$1={BOTH:3,COLUMN:2,NO_STATUS:0,ROW:1};let Ee$1 = class Ee extends Bi{__colSpan;__rowSpan;__headerState;__width;__backgroundColor;__verticalAlign;static getType(){return "tablecell"}static clone(e){return new Ee(e.__headerState,e.__colSpan,e.__width,e.__key)}afterCloneFrom(e){super.afterCloneFrom(e),this.__rowSpan=e.__rowSpan,this.__backgroundColor=e.__backgroundColor,this.__verticalAlign=e.__verticalAlign,this.__colSpan=e.__colSpan,this.__headerState=e.__headerState,this.__width=e.__width;}static importDOM(){return {td:e=>({conversion:Me$1,priority:0}),th:e=>({conversion:Me$1,priority:0})}}static importJSON(e){return $e$1().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setHeaderStyles(e.headerState).setColSpan(e.colSpan||1).setRowSpan(e.rowSpan||1).setWidth(e.width||void 0).setBackgroundColor(e.backgroundColor||null).setVerticalAlign(e.verticalAlign||void 0)}constructor(e=Ae$1.NO_STATUS,t=1,n,o){super(o),this.__colSpan=t,this.__rowSpan=1,this.__headerState=e,this.__width=n,this.__backgroundColor=null,this.__verticalAlign=void 0;}createDOM(t){const n=document.createElement(this.getTag());return this.__width&&(n.style.width=`${this.__width}px`),this.__colSpan>1&&(n.colSpan=this.__colSpan),this.__rowSpan>1&&(n.rowSpan=this.__rowSpan),null!==this.__backgroundColor&&(n.style.backgroundColor=this.__backgroundColor),ke$1(this.__verticalAlign)&&(n.style.verticalAlign=this.__verticalAlign),mc(n,t.theme.tableCell,this.hasHeader()&&t.theme.tableCellHeader),n}exportDOM(e){const t=super.exportDOM(e);if(Ys(t.element)){const e=t.element;e.setAttribute("data-temporary-table-cell-lexical-key",this.getKey()),e.style.border="1px solid black",this.__colSpan>1&&(e.colSpan=this.__colSpan),this.__rowSpan>1&&(e.rowSpan=this.__rowSpan),e.style.width=`${this.getWidth()||75}px`,e.style.verticalAlign=this.getVerticalAlign()||"top",e.style.textAlign="start",null===this.__backgroundColor&&this.hasHeader()&&(e.style.backgroundColor="#f2f3f5");}return t}exportJSON(){return {...super.exportJSON(),...ke$1(this.__verticalAlign)&&{verticalAlign:this.__verticalAlign},backgroundColor:this.getBackgroundColor(),colSpan:this.__colSpan,headerState:this.__headerState,rowSpan:this.__rowSpan,width:this.getWidth()}}getColSpan(){return this.getLatest().__colSpan}setColSpan(e){const t=this.getWritable();return t.__colSpan=e,t}getRowSpan(){return this.getLatest().__rowSpan}setRowSpan(e){const t=this.getWritable();return t.__rowSpan=e,t}getTag(){return this.hasHeader()?"th":"td"}setHeaderStyles(e,t=Ae$1.BOTH){const n=this.getWritable();return n.__headerState=e&t|n.__headerState&~t,n}getHeaderStyles(){return this.getLatest().__headerState}setWidth(e){const t=this.getWritable();return t.__width=e,t}getWidth(){return this.getLatest().__width}getBackgroundColor(){return this.getLatest().__backgroundColor}setBackgroundColor(e){const t=this.getWritable();return t.__backgroundColor=e,t}getVerticalAlign(){return this.getLatest().__verticalAlign}setVerticalAlign(e){const t=this.getWritable();return t.__verticalAlign=e||void 0,t}toggleHeaderStyle(e){const t=this.getWritable();return (t.__headerState&e)===e?t.__headerState-=e:t.__headerState+=e,t}hasHeaderState(e){return (this.getHeaderStyles()&e)===e}hasHeader(){return this.getLatest().__headerState!==Ae$1.NO_STATUS}updateDOM(e){return e.__headerState!==this.__headerState||e.__width!==this.__width||e.__colSpan!==this.__colSpan||e.__rowSpan!==this.__rowSpan||e.__backgroundColor!==this.__backgroundColor||e.__verticalAlign!==this.__verticalAlign}isShadowRoot(){return true}collapseAtStart(){return true}canBeEmpty(){return false}canIndent(){return false}};function ke$1(e){return "middle"===e||"bottom"===e}function Me$1(e){const t=e,n=e.nodeName.toLowerCase();let o;Ke$1.test(t.style.width)&&(o=parseFloat(t.style.width));let r=Ae$1.NO_STATUS;if("th"===n){const e=t.getAttribute("scope");if("col"===e)r=Ae$1.COLUMN;else if("row"===e)r=Ae$1.ROW;else {const e=t.parentElement,n=Ys(e)&&"tr"===e.nodeName.toLowerCase()&&Ys(e.parentElement)&&("thead"===e.parentElement.nodeName.toLowerCase()||0===e.rowIndex),o=0===t.cellIndex;n&&(r|=Ae$1.ROW),o&&(r|=Ae$1.COLUMN),r===Ae$1.NO_STATUS&&(r=Ae$1.ROW);}}const l=$e$1(r,t.colSpan,o);l.__rowSpan=t.rowSpan;const s=t.style.backgroundColor;""!==s&&(l.__backgroundColor=s);const i=t.style.verticalAlign;ke$1(i)&&(l.__verticalAlign=i);const c=t.style,a=(c&&c.textDecoration||"").split(" "),u="700"===c.fontWeight||"bold"===c.fontWeight,h=a.includes("line-through"),C="italic"===c.fontStyle,_=a.includes("underline"),S=c.color;return {after:e=>{const t=[];let n=null;const o=()=>{if(n){const e=n.getFirstChild();sr(e)&&1===n.getChildrenSize()&&e.remove();}};for(const r of e)if(Fs(r)||Tr(r)||sr(r)){if(Tr(r)&&(u&&r.toggleFormat("bold"),h&&r.toggleFormat("strikethrough"),C&&r.toggleFormat("italic"),_&&r.toggleFormat("underline"),S)){const e=r.getStyle();e.includes("color:")||r.setStyle(e+`color: ${S};`);}n?n.append(r):(n=eo().append(r),t.push(n));}else t.push(r),o(),n=null;return o(),0===t.length&&t.push(eo()),t},node:l}}function $e$1(e=Ae$1.NO_STATUS,t=1,n){return zs(new Ee$1(e,t,n))}function We$1(e){return e instanceof Ee$1}const ze$1=re$5("INSERT_TABLE_COMMAND");function Le$1(e,...t){const n=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",e);for(const e of t)o.append("v",e);throw n.search=o.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}let He$1 = class He extends Bi{__height;static getType(){return "tablerow"}static clone(e){return new He(e.__height,e.__key)}afterCloneFrom(e){super.afterCloneFrom(e),this.__height=e.__height;}static importDOM(){return {tr:e=>({conversion:Be$1,priority:0})}}static importJSON(e){return Pe$1().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setHeight(e.height)}constructor(e,t){super(t),this.__height=e;}exportJSON(){const e=this.getHeight();return {...super.exportJSON(),...void 0===e?void 0:{height:e}}}createDOM(t){const n=document.createElement("tr");return this.__height&&(n.style.height=`${this.__height}px`),mc(n,t.theme.tableRow),n}extractWithChild(e,t,n){return "html"===n}isShadowRoot(){return true}setHeight(e){const t=this.getWritable();return t.__height=e,t}getHeight(){return this.getLatest().__height}updateDOM(e){return e.__height!==this.__height}canBeEmpty(){return false}canIndent(){return false}};function Be$1(e){const n=e;let o;return Ke$1.test(n.style.height)&&(o=parseFloat(n.style.height)),{after:e=>Ht$3(e,We$1),node:Pe$1(o)}}function Pe$1(e){return zs(new He$1(e))}function De$1(e){return e instanceof He$1}const Ie$1="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,Ue$1=Ie$1&&"documentMode"in document?document.documentMode:null,Je$1=Ie$1&&/^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);function Xe$1(e,t,n=true){const o=Fn();for(let r=0;r<e;r++){const e=Pe$1();for(let o=0;o<t;o++){let t=Ae$1.NO_STATUS;"object"==typeof n?(0===r&&n.rows&&(t|=Ae$1.ROW),0===o&&n.columns&&(t|=Ae$1.COLUMN)):n&&(0===r&&(t|=Ae$1.ROW),0===o&&(t|=Ae$1.COLUMN));const l=$e$1(t),s=eo();s.append(kr()),l.append(s),e.append(l);}o.append(e);}return o}function Ye(e){const t=dl(e,e=>We$1(e));return We$1(t)?t:null}function qe$1(e){const t=dl(e,e=>De$1(e));if(De$1(t))return t;throw new Error("Expected table cell to be inside of table row.")}function je$1(e){const t=dl(e,e=>Rn(e));if(Rn(t))return t;throw new Error("Expected table cell to be inside of table.")}function Ve$1(e){const t=qe$1(e);return je$1(t).getChildren().findIndex(e=>e.is(t))}function Ge$1(e){return qe$1(e).getChildren().findIndex(t=>t.is(e))}Ie$1&&"InputEvent"in window&&!Ue$1&&new window.InputEvent("input");const tt=(e,t)=>e===Ae$1.BOTH||e===t?t:Ae$1.NO_STATUS;function nt(e=true){const t=Qr();Fr(t)||Ot(t)||Le$1(188);const n=t.anchor.getNode(),o=t.focus.getNode(),[r]=yt(n),[l,,s]=yt(o),[,i,c]=wt(s,l,r),{startRow:a}=c,{startRow:u}=i;return e?rt(a+r.__rowSpan>u+l.__rowSpan?r:l,true):rt(u<a?l:r,false)}function rt(e,t=true){const[,,n]=yt(e),[o,r]=wt(n,e,e),l=o[0].length,{startRow:s}=r;let i=null;if(t){const t=s+e.__rowSpan-1,r=o[t],c=Pe$1();for(let e=0;e<l;e++){const{cell:n,startRow:o}=r[e];if(o+n.__rowSpan-1<=t){const t=r[e].cell.__headerState,n=tt(t,Ae$1.COLUMN);c.append($e$1(n).append(eo()));}else n.setRowSpan(n.__rowSpan+1);}const a=n.getChildAtIndex(t);De$1(a)||Le$1(256),a.insertAfter(c),i=c;}else {const e=s,t=o[e],r=Pe$1();for(let n=0;n<l;n++){const{cell:o,startRow:l}=t[n];if(l===e){const e=t[n].cell.__headerState,o=tt(e,Ae$1.COLUMN);r.append($e$1(o).append(eo()));}else o.setRowSpan(o.__rowSpan+1);}const c=n.getChildAtIndex(e);De$1(c)||Le$1(257),c.insertBefore(r),i=r;}return i}function st(e=true){const t=Qr();Fr(t)||Ot(t)||Le$1(188);const n=t.anchor.getNode(),o=t.focus.getNode(),[r]=yt(n),[l,,s]=yt(o),[,i,c]=wt(s,l,r),{startColumn:a}=c,{startColumn:u}=i;return e?ct(a+r.__colSpan>u+l.__colSpan?r:l,true):ct(u<a?l:r,false)}function ct(e,t=true,n=true){const[,,o]=yt(e),[r,l]=wt(o,e,e),s=r.length,{startColumn:i}=l,c=t?i+e.__colSpan-1:i-1,a=o.getFirstChild();De$1(a)||Le$1(120);let u=null;function h(e=Ae$1.NO_STATUS){const t=$e$1(e).append(eo());return null===u&&(u=t),t}let d=a;e:for(let e=0;e<s;e++){if(0!==e){const e=d.getNextSibling();De$1(e)||Le$1(121),d=e;}const t=r[e],n=t[c<0?0:c].cell.__headerState,o=tt(n,Ae$1.ROW);if(c<0){mt(d,h(o));continue}const{cell:l,startColumn:s,startRow:i}=t[c];if(s+l.__colSpan-1<=c){let n=l,r=i,s=c;for(;r!==e&&n.__rowSpan>1;){if(s-=l.__colSpan,!(s>=0)){d.append(h(o));continue e}{const{cell:e,startRow:o}=t[s];n=e,r=o;}}n.insertAfter(h(o));}else l.setColSpan(l.__colSpan+1);}null!==u&&n&&gt(u);const f=o.getColWidths();if(f){const e=[...f],t=c<0?0:c,n=e[t];e.splice(t,0,n),o.setColWidths(e);}return u}function ut(){const e=Qr();Fr(e)||Ot(e)||Le$1(188);const[t,n]=e.isBackward()?[e.focus.getNode(),e.anchor.getNode()]:[e.anchor.getNode(),e.focus.getNode()],[o,,r]=yt(t),[l]=yt(n),[s,i,c]=wt(r,o,l),{startRow:a}=i,{startRow:u}=c,h=u+l.__rowSpan-1;if(s.length===h-a+1)return void r.remove();const d=s[0].length,f=s[h+1],g=r.getChildAtIndex(h+1);for(let e=h;e>=a;e--){for(let t=d-1;t>=0;t--){const{cell:n,startRow:o,startColumn:r}=s[e][t];if(r===t){if(o<a||o+n.__rowSpan-1>h){const e=Math.max(o,a),t=Math.min(n.__rowSpan+o-1,h),r=e<=t?t-e+1:0;n.setRowSpan(n.__rowSpan-r);}if(o>=a&&o+n.__rowSpan-1>h&&e===h){null===g&&Le$1(122);let o=null;for(let n=0;n<t;n++){const t=f[n],r=t.cell;t.startRow===e+1&&(o=r),r.__colSpan>1&&(n+=r.__colSpan-1);}null===o?mt(g,n):o.insertAfter(n);}}}const t=r.getChildAtIndex(e);De$1(t)||Le$1(206,String(e)),t.remove();}if(void 0!==f){const{cell:e}=f[0];gt(e);}else {const e=s[a-1],{cell:t}=e[0];gt(t);}}function dt(){const e=Qr();Fr(e)||Ot(e)||Le$1(188);const t=e.anchor.getNode(),n=e.focus.getNode(),[o,,r]=yt(t),[l]=yt(n),[s,i,c]=wt(r,o,l),{startColumn:a}=i,{startRow:u,startColumn:h}=c,d=Math.min(a,h),f=Math.max(a+o.__colSpan-1,h+l.__colSpan-1),g=f-d+1;if(s[0].length===f-d+1)return r.selectPrevious(),void r.remove();const m=s.length;for(let e=0;e<m;e++)for(let t=d;t<=f;t++){const{cell:n,startColumn:o}=s[e][t];if(o<d){if(t===d){const e=d-o;n.setColSpan(n.__colSpan-Math.min(g,n.__colSpan-e));}}else if(o+n.__colSpan-1>f){if(t===f){const e=f-o+1;n.setColSpan(n.__colSpan-e);}}else n.remove();}const p=s[u],C=a>h?p[a+o.__colSpan]:p[h+l.__colSpan];if(void 0!==C){const{cell:e}=C;gt(e);}else {const e=h<a?p[h-1]:p[a-1],{cell:t}=e;gt(t);}const _=r.getColWidths();if(_){const e=[..._];e.splice(d,g),r.setColWidths(e);}}function gt(e){const t=e.getFirstDescendant();null==t?e.selectStart():t.getParentOrThrow().selectStart();}function mt(e,t){const n=e.getFirstChild();null!==n?n.insertBefore(t):e.append(t);}function pt(e){if(0===e.length)return null;const t=je$1(e[0]),[n]=bt(t,null,null);let o=1/0,r=-1/0,l=1/0,s=-1/0;const i=new Set;for(const t of n)for(const n of t){if(!n||!n.cell)continue;const t=n.cell.getKey();if(!i.has(t)&&e.some(e=>e.is(n.cell))){i.add(t);const e=n.startRow,c=n.startColumn,a=n.cell.__rowSpan||1,u=n.cell.__colSpan||1;o=Math.min(o,e),r=Math.max(r,e+a-1),l=Math.min(l,c),s=Math.max(s,c+u-1);}}if(o===1/0||l===1/0)return null;const c=r-o+1,a=s-l+1,u=n[o][l];if(!u.cell)return null;const h=u.cell;h.setColSpan(a),h.setRowSpan(c);const d=new Set([h.getKey()]);for(let e=o;e<=r;e++)for(let t=l;t<=s;t++){const o=n[e][t];if(!o.cell)continue;const r=o.cell,l=r.getKey();if(!d.has(l)){d.add(l);Ct(r)||h.append(...r.getChildren()),r.remove();}}return 0===h.getChildrenSize()&&h.append(eo()),h}function Ct(e){if(1!==e.getChildrenSize())return false;const t=e.getFirstChildOrThrow();return !(!no(t)||!t.isEmpty())}function St(e){const[t,n,o]=yt(e),r=t.__colSpan,l=t.__rowSpan;if(1===r&&1===l)return;const[s,i]=wt(o,t,t),{startColumn:c,startRow:a}=i,u=t.__headerState&Ae$1.COLUMN,h=Array.from({length:r},(e,t)=>{let n=u;for(let e=0;0!==n&&e<s.length;e++)n&=s[e][t+c].cell.__headerState;return n}),d=t.__headerState&Ae$1.ROW,f=Array.from({length:l},(e,t)=>{let n=d;for(let e=0;0!==n&&e<s[0].length;e++)n&=s[t+a][e].cell.__headerState;return n});if(r>1){for(let e=1;e<r;e++)t.insertAfter($e$1(h[e]|f[0]).append(eo()));t.setColSpan(1);}if(l>1){let e;for(let t=1;t<l;t++){const o=a+t,l=s[o];e=(e||n).getNextSibling(),De$1(e)||Le$1(125);let i=null;for(let e=0;e<c;e++){const t=l[e],n=t.cell;t.startRow===o&&(i=n),n.__colSpan>1&&(e+=n.__colSpan-1);}if(null===i)for(let n=r-1;n>=0;n--)mt(e,$e$1(h[n]|f[t]).append(eo()));else for(let e=r-1;e>=0;e--)i.insertAfter($e$1(h[e]|f[t]).append(eo()));}t.setRowSpan(1);}}function wt(e,t,n){const[o,r,l]=bt(e,t,n);return null===r&&Le$1(207),null===l&&Le$1(208),[o,r,l]}function bt(e,t,n){const o=[];let r=null,l=null;function s(e){let t=o[e];return void 0===t&&(o[e]=t=[]),t}const i=e.getChildren();for(let e=0;e<i.length;e++){const o=i[e];De$1(o)||Le$1(209);const c=s(e);for(let a=o.getFirstChild(),u=0;null!=a;a=a.getNextSibling()){for(We$1(a)||Le$1(147);void 0!==c[u];)u++;const o={cell:a,startColumn:u,startRow:e},{__rowSpan:h,__colSpan:d}=a;for(let t=0;t<h&&!(e+t>=i.length);t++){const n=s(e+t);for(let e=0;e<d;e++)n[u+e]=o;}null!==t&&null===r&&t.is(a)&&(r=o),null!==n&&null===l&&n.is(a)&&(l=o);}}return [o,r,l]}function yt(e){let t;if(e instanceof Ee$1)t=e;else if("__type"in e){const o=dl(e,We$1);We$1(o)||Le$1(148),t=o;}else {const o=dl(e.getNode(),We$1);We$1(o)||Le$1(148),t=o;}const o=t.getParent();De$1(o)||Le$1(149);const r=o.getParent();return Rn(r)||Le$1(210),[t,o,r]}function Nt(e,t,n){let o,r=Math.min(t.startColumn,n.startColumn),l=Math.min(t.startRow,n.startRow),s=Math.max(t.startColumn+t.cell.__colSpan-1,n.startColumn+n.cell.__colSpan-1),i=Math.max(t.startRow+t.cell.__rowSpan-1,n.startRow+n.cell.__rowSpan-1);do{o=false;for(let t=0;t<e.length;t++)for(let n=0;n<e[0].length;n++){const c=e[t][n];if(!c)continue;const a=c.startColumn+c.cell.__colSpan-1,u=c.startRow+c.cell.__rowSpan-1,h=c.startColumn<=s&&a>=r,d=c.startRow<=i&&u>=l;if(h&&d){const e=Math.min(r,c.startColumn),t=Math.max(s,a),n=Math.min(l,c.startRow),h=Math.max(i,u);e===r&&t===s&&n===l&&h===i||(r=e,s=t,l=n,i=h,o=true);}}}while(o);return {maxColumn:s,maxRow:i,minColumn:r,minRow:l}}function Tt(e){const[t,,n]=yt(e),o=n.getChildren(),r=o.length,l=o[0].getChildren().length,s=new Array(r);for(let e=0;e<r;e++)s[e]=new Array(l);for(let e=0;e<r;e++){const n=o[e].getChildren();let r=0;for(let o=0;o<n.length;o++){for(;s[e][r];)r++;const l=n[o],i=l.__rowSpan||1,c=l.__colSpan||1;for(let t=0;t<i;t++)for(let n=0;n<c;n++)s[e+t][r+n]=l;if(t===l)return {colSpan:c,columnIndex:r,rowIndex:e,rowSpan:i};r+=c;}}return null}function Ft(e){const[[t,o,r,l],[s,i,c,a]]=["anchor","focus"].map(t=>{const o=e[t].getNode(),r=dl(o,We$1);We$1(r)||Le$1(238,t,o.getKey(),o.getType());const l=r.getParent();De$1(l)||Le$1(239,t);const s=l.getParent();return Rn(s)||Le$1(240,t),[o,r,l,s]});return l.is(a)||Le$1(241),{anchorCell:o,anchorNode:t,anchorRow:r,anchorTable:l,focusCell:i,focusNode:s,focusRow:c,focusTable:a}}class Rt{tableKey;anchor;focus;_cachedNodes;dirty;constructor(e,t,n){this.anchor=t,this.focus=n,t._selection=this,n._selection=this,this._cachedNodes=null,this.dirty=false,this.tableKey=e;}getStartEndPoints(){return [this.anchor,this.focus]}isValid(){if("root"===this.tableKey||"root"===this.anchor.key||"element"!==this.anchor.type||"root"===this.focus.key||"element"!==this.focus.type)return false;const e=Yo(this.tableKey),t=Yo(this.anchor.key),n=Yo(this.focus.key);return null!==e&&null!==t&&null!==n}isBackward(){return this.focus.isBefore(this.anchor)}getCachedNodes(){return this._cachedNodes}setCachedNodes(e){this._cachedNodes=e;}is(e){return Ot(e)&&this.tableKey===e.tableKey&&this.anchor.is(e.anchor)&&this.focus.is(e.focus)}set(e,t,n){this.dirty=this.dirty||e!==this.tableKey||t!==this.anchor.key||n!==this.focus.key,this.tableKey=e,this.anchor.key=t,this.focus.key=n,this._cachedNodes=null;}clone(){return new Rt(this.tableKey,Mr(this.anchor.key,this.anchor.offset,this.anchor.type),Mr(this.focus.key,this.focus.offset,this.focus.type))}isCollapsed(){return false}extract(){return this.getNodes()}insertRawText(e){}insertText(){}hasFormat(e){let t=0;this.getNodes().filter(We$1).forEach(e=>{const n=e.getFirstChild();no(n)&&(t|=n.getTextFormat());});const n=z$7[e];return 0!==(t&n)}insertNodes(e){const t=this.focus.getNode();Wi(t)||Le$1(151);St$3(t.select(0,t.getChildrenSize())).insertNodes(e);}getShape(){const{anchorCell:e,focusCell:t}=Ft(this),n=Tt(e);null===n&&Le$1(153);const o=Tt(t);null===o&&Le$1(155);const r=Math.min(n.columnIndex,o.columnIndex),l=Math.max(n.columnIndex+n.colSpan-1,o.columnIndex+o.colSpan-1),s=Math.min(n.rowIndex,o.rowIndex),i=Math.max(n.rowIndex+n.rowSpan-1,o.rowIndex+o.rowSpan-1);return {fromX:Math.min(r,l),fromY:Math.min(s,i),toX:Math.max(r,l),toY:Math.max(s,i)}}getNodes(){if(!this.isValid())return [];const e=this._cachedNodes;if(null!==e)return e;const{anchorTable:t,anchorCell:n,focusCell:o}=Ft(this),r=o.getParents()[1];if(r!==t){if(t.isParentOf(o)){const e=r.getParent();null==e&&Le$1(159),this.set(this.tableKey,o.getKey(),e.getKey());}else {const e=t.getParent();null==e&&Le$1(158),this.set(this.tableKey,e.getKey(),o.getKey());}return this.getNodes()}const[l,s,i]=wt(t,n,o),{minColumn:c,maxColumn:a,minRow:u,maxRow:h}=Nt(l,s,i),d=new Map([[t.getKey(),t]]);let f=null;for(let e=u;e<=h;e++)for(let t=c;t<=a;t++){const{cell:n}=l[e][t],o=n.getParent();De$1(o)||Le$1(160),o!==f&&(d.set(o.getKey(),o),f=o),d.has(n.getKey())||Et(n,e=>{d.set(e.getKey(),e);});}const g=Array.from(d.values());return mi()||(this._cachedNodes=g),g}getTextContent(){const e=this.getNodes().filter(e=>We$1(e));let t="";for(let n=0;n<e.length;n++){const o=e[n],r=o.__parent,l=(e[n+1]||{}).__parent;t+=o.getTextContent()+(l!==r?"\n":"\t");}return t}}function Ot(e){return e instanceof Rt}function Kt(){const e=Mr("root",0,"element"),t=Mr("root",0,"element");return new Rt("root",e,t)}function At(e,t,n){e.getKey(),t.getKey(),n.getKey();const o=Qr(),r=Ot(o)?o.clone():Kt();return r.set(e.getKey(),t.getKey(),n.getKey()),r}function Et(e,t){const n=[[e]];for(let e=n.at(-1);void 0!==e&&n.length>0;e=n.at(-1)){const o=e.pop();void 0===o?n.pop():false!==t(o)&&Wi(o)&&n.push(o.getChildren());}}function kt(e,t=Zs()){const n=Yo(e);Rn(n)||Le$1(231,e);const o=Lt(n,t.getElementByKey(e));return null===o&&Le$1(232,e),{tableElement:o,tableNode:n}}class Mt{observers;nextFocus;shouldCheckSelectionForTable;constructor(){this.observers=new Map,this.nextFocus=null,this.shouldCheckSelectionForTable=null;}setNextFocus(e){this.nextFocus=e;}getAndClearNextFocus(){const{nextFocus:e}=this;return null!==e&&(this.nextFocus=null),e}setShouldCheckSelectionForTable(e){this.shouldCheckSelectionForTable=e;}getAndClearShouldCheckSelectionForTable(){const{shouldCheckSelectionForTable:e}=this;return e?(this.shouldCheckSelectionForTable=null,e):null}}class $t{focusX;focusY;listenersToRemove;table;isHighlightingCells;anchorX;anchorY;tableNodeKey;anchorCell;focusCell;anchorCellNodeKey;focusCellNodeKey;editor;tableSelection;hasHijackedSelectionStyles;isSelecting;pointerType;abortController;listenerOptions;constructor(e,t){this.isHighlightingCells=false,this.anchorX=-1,this.anchorY=-1,this.focusX=-1,this.focusY=-1,this.listenersToRemove=new Set,this.tableNodeKey=t,this.editor=e,this.table={columns:0,domRows:[],rows:0},this.tableSelection=null,this.anchorCellNodeKey=null,this.focusCellNodeKey=null,this.anchorCell=null,this.focusCell=null,this.hasHijackedSelectionStyles=false,this.isSelecting=false,this.pointerType=null,this.abortController=new AbortController,this.listenerOptions={signal:this.abortController.signal},this.trackTable();}getTable(){return this.table}removeListeners(){this.abortController.abort("removeListeners"),Array.from(this.listenersToRemove).forEach(e=>e()),this.listenersToRemove.clear();}$lookup(){return kt(this.tableNodeKey,this.editor)}trackTable(){const e=new MutationObserver(e=>{this.editor.getEditorState().read(()=>{let t=false;for(let n=0;n<e.length;n++){const o=e[n].target.nodeName;if("TABLE"===o||"TBODY"===o||"THEAD"===o||"TR"===o){t=true;break}}if(!t)return;const{tableNode:n,tableElement:o}=this.$lookup();this.table=Gt(n,o);},{editor:this.editor});});this.editor.getEditorState().read(()=>{const{tableNode:t,tableElement:n}=this.$lookup();this.table=Gt(t,n),e.observe(n,{attributes:true,childList:true,subtree:true});},{editor:this.editor});}$clearHighlight(e=true){const t=this.editor;this.isHighlightingCells=false,this.anchorX=-1,this.anchorY=-1,this.focusX=-1,this.focusY=-1,this.tableSelection=null,this.anchorCellNodeKey=null,this.focusCellNodeKey=null,this.anchorCell=null,this.focusCell=null,this.hasHijackedSelectionStyles=false,this.$enableHighlightStyle();const{tableNode:n,tableElement:o}=this.$lookup();Qt(t,Gt(n,o),null),e&&null!==Qr()&&(es(null),t.dispatchCommand(ie$4,void 0));}$enableHighlightStyle(){const e=this.editor,{tableElement:t}=this.$lookup();xc(t,e._config.theme.tableSelection),t.classList.remove("disable-selection"),this.hasHijackedSelectionStyles=false;}$disableHighlightStyle(){const{tableElement:t}=this.$lookup();mc(t,this.editor._config.theme.tableSelection),this.hasHijackedSelectionStyles=true;}$updateTableTableSelection(e){if(null!==e){e.tableKey!==this.tableNodeKey&&Le$1(233,e.tableKey,this.tableNodeKey);const t=this.editor;this.tableSelection=e,this.isHighlightingCells=true,this.$disableHighlightStyle(),this.updateDOMSelection(),Qt(t,this.table,this.tableSelection);}else this.$clearHighlight();}updateDOMSelection(){if(null!==this.anchorCell&&null!==this.focusCell){const e=Js(this.editor._window);e&&e.rangeCount>0&&e.removeAllRanges();}}$setFocusCellForSelection(e,t=false){const n=this.editor,{tableNode:o}=this.$lookup(),r=e.x,l=e.y;if(this.focusCell=e,!this.isHighlightingCells){(t||this.anchorX!==r||this.anchorY!==l||null!=this.tableSelection&&null!=this.anchorCellNodeKey)&&(this.isHighlightingCells=true,this.$disableHighlightStyle());}if(-1!==this.focusX&&-1!==this.focusY&&r===this.focusX&&l===this.focusY)return false;if(this.focusX=r,this.focusY=l,this.isHighlightingCells){const s=_n(o,e.elem);if(null!=this.tableSelection&&null!=this.anchorCellNodeKey){let e=s;if(null===e&&t&&(e=o.getCellNodeFromCords(r,l,this.table)),null!==e){const t=this.$getAnchorTableCellOrThrow();return this.focusCellNodeKey=e.getKey(),this.tableSelection=At(o,t,e),es(this.tableSelection),n.dispatchCommand(ie$4,void 0),Qt(n,this.table,this.tableSelection),true}}}return false}$getAnchorTableCell(){return this.anchorCellNodeKey?Yo(this.anchorCellNodeKey):null}$getAnchorTableCellOrThrow(){const e=this.$getAnchorTableCell();return null===e&&Le$1(234),e}$getFocusTableCell(){return this.focusCellNodeKey?Yo(this.focusCellNodeKey):null}$getFocusTableCellOrThrow(){const e=this.$getFocusTableCell();return null===e&&Le$1(235),e}$setAnchorCellForSelection(e){this.isHighlightingCells=false,this.anchorCell=e,this.anchorX=e.x,this.anchorY=e.y,this.focusX=-1,this.focusY=-1,this.focusCell=null,this.focusCellNodeKey=null;const{tableNode:t}=this.$lookup(),n=_n(t,e.elem);if(null!==n){const e=n.getKey();null!=this.tableSelection?(this.tableSelection=this.tableSelection.clone(),this.tableSelection.set(t.getKey(),e,e)):this.tableSelection=At(t,n,n),this.anchorCellNodeKey=e;}}$formatCells(e){const t=Qr();Ot(t)||Le$1(236);const n=qr(),o=n.anchor,r=n.focus,l=t.getNodes().filter(We$1);l.length>0||Le$1(237);const s=l[0].getFirstChild(),i=no(s)?s.getFormatFlags(e,null):null;l.forEach(t=>{o.set(t.getKey(),0,"element"),r.set(t.getKey(),t.getChildrenSize(),"element"),n.formatText(e,i);}),es(t),this.editor.dispatchCommand(ie$4,void 0);}$clearText(){const{editor:e}=this,t=Yo(this.tableNodeKey);if(!Rn(t))throw new Error("Expected TableNode.");const n=Qr();Ot(n)||Le$1(253);const o=n.getNodes().filter(We$1),r=t.getFirstChild(),l=t.getLastChild();if(o.length>0&&null!==r&&null!==l&&De$1(r)&&De$1(l)&&o[0]===r.getFirstChild()&&o[o.length-1]===l.getLastChild()){t.selectPrevious();const n=t.getParent();return t.remove(),void(Vi(n)&&n.isEmpty()&&e.dispatchCommand(he$3,void 0))}o.forEach(e=>{if(Wi(e)){const t=eo(),n=kr();t.append(n),e.append(t),e.getChildren().forEach(e=>{e!==t&&e.remove();});}}),Qt(e,this.table,null),es(null),e.dispatchCommand(ie$4,void 0);}}const Wt="__lexicalTableSelection";function zt(e){return Ys(e)&&"TABLE"===e.nodeName}function Lt(e,t){if(!t)return t;const n=zt(t)?t:t.querySelector("table");return zt(n)||Le$1(341,e.constructor.name,e.getType(),e.getKey(),t.nodeName),n}function Ht(e){return e._window}function Bt(e,t){for(let n=t,o=null;null!==n;n=n.getParent()){if(e.is(n))return o;We$1(n)&&(o=n);}return null}const Pt=[[Ee$3,"down"],[we$1,"up"],[Ne$1,"backward"],[ke$2,"forward"]],Dt=[ye$2,me$3,fe$4],It=[Ae$3,Pe$2];function Ut(e,t){const n=e.getRootElement(),o=e._window;if(!n||!o)return ()=>{};const r=o=>{const r=o.target;if(0!==o.button||!qs(r)||!n.contains(r))return;const l=function(e){const t=jt(e);if(null===t)return null;let n=t.elem;for(;null!=n;){if("TABLE"===n.nodeName&&Wt in n&&n[Wt])return {cellElement:t,tableElement:n,tableObserver:n[Wt]};n=n.parentNode;}return null}(r);e.update(()=>{if(Ot(Qr())){for(const[e]of t.observers.values())e.$clearHighlight(false);es(null),e.dispatchCommand(ie$4,void 0);}if(!l)return;const{tableObserver:n,tableElement:r,cellElement:s}=l;!function(e,t,n,o,r,l){const s=e._window;if(!s)return;const i=t=>{if(r.isSelecting)return;r.isSelecting=true,null!==t&&null===r.anchorCell&&e.update(()=>{r.$setAnchorCellForSelection(t);});const n=()=>{r.isSelecting=false,s.removeEventListener("pointerup",n),s.removeEventListener("pointermove",i);},i=t=>{if(!(e=>!(1&~e.buttons))(t)&&r.isSelecting)return r.isSelecting=false,s.removeEventListener("pointerup",n),void s.removeEventListener("pointermove",i);if(!qs(t.target))return;let c=null;const a=!(Je$1||o.contains(t.target));if(a)c=Vt(o,t.target);else for(const e of document.elementsFromPoint(t.clientX,t.clientY))if(c=Vt(o,e),c)break;if(c){const t=c;null===r.anchorCell&&e.update(()=>{r.$setAnchorCellForSelection(t);}),null!==r.focusCell&&c.elem===r.focusCell.elem||(l.setNextFocus({focusCell:c,override:a,tableKey:r.tableNodeKey}),e.dispatchCommand(ie$4,void 0));}};s.addEventListener("pointerup",n,r.listenerOptions),s.addEventListener("pointermove",i,r.listenerOptions);};r.pointerType=t.pointerType;const c=Bs(r.tableNodeKey),a=Zr();if(Je$1&&t.shiftKey&&ln(a,c)&&(Fr(a)||Ot(a))){const e=a.anchor.getNode(),o=Bt(c,a.anchor.getNode());if(o)r.$setAnchorCellForSelection(Cn(r,o)),r.$setFocusCellForSelection(n),gn(t);else {(c.isBefore(e)?c.selectStart():c.selectEnd()).anchor.set(a.anchor.key,a.anchor.offset,a.anchor.type);}}else "touch"!==t.pointerType&&r.$setAnchorCellForSelection(n);i(n);}(e,o,s,r,n,t);});};return o.addEventListener("pointerdown",r),()=>{o.removeEventListener("pointerdown",r);}}function Jt(e,t,o,l,s){const i=o.getRootElement(),c=Ht(o);null!==i&&null!==c||Le$1(246);const a=new $t(o,e.getKey()),u=Lt(e,t);!function(e,t){null!==qt(e)&&Le$1(205);e[Wt]=t;}(u,a),a.listenersToRemove.add(()=>function(e,t){qt(e)===t&&delete e[Wt];}(u,a));const h=e=>{if(e.detail>=3&&qs(e.target)){null!==jt(e.target)&&e.preventDefault();}};u.addEventListener("mousedown",h,a.listenerOptions),a.listenersToRemove.add(()=>{u.removeEventListener("mousedown",h);});for(const[t,n]of Pt)a.listenersToRemove.add(o.registerCommand(t,t=>fn(o,t,n,e,a,s),so));a.listenersToRemove.add(o.registerCommand(De$2,t=>{const n=Qr();if(Ot(n)){const o=Bt(e,n.focus.getNode());if(null!==o)return gn(t),o.selectEnd(),true}return false},so));const d=t=>()=>{const o=Qr();if(!ln(o,e))return false;if(Ot(o))return a.$clearText(),true;if(Fr(o)){if(!We$1(Bt(e,o.anchor.getNode())))return false;const r=o.anchor.getNode(),l=o.focus.getNode(),s=e.isParentOf(r),i=e.isParentOf(l);if(s&&!i||i&&!s)return a.$clearText(),true;const c=dl(o.anchor.getNode(),e=>Wi(e)),u=c&&dl(c,e=>Wi(e)&&We$1(e.getParent()));if(!Wi(u)||!Wi(c))return false;if(t===me$3&&null===u.getPreviousSibling())return true}return false};for(const e of Dt)a.listenersToRemove.add(o.registerCommand(e,d(e),so));const f=t=>{const n=Qr();if(!Ot(n)&&!Fr(n))return false;const o=e.isParentOf(n.anchor.getNode());if(o!==e.isParentOf(n.focus.getNode())){const t=o?"anchor":"focus",r=o?"focus":"anchor",{key:l,offset:s,type:i}=n[r];return e[n[t].isBefore(n[r])?"selectPrevious":"selectNext"]()[r].set(l,s,i),false}return !!ln(n,e)&&(!!Ot(n)&&(t&&(t.preventDefault(),t.stopPropagation()),a.$clearText(),true))};for(const e of It)a.listenersToRemove.add(o.registerCommand(e,f,so));return a.listenersToRemove.add(o.registerCommand(je$2,e=>{const t=Qr();if(t){if(!Ot(t)&&!Fr(t))return false;V$4(o,Bt$3(e,ClipboardEvent)?e:null,et(t));const n=f(e);return Fr(t)?(t.removeText(),true):n}return false},so)),a.listenersToRemove.add(o.registerCommand(xe,t=>{const o=Qr();if(!ln(o,e))return false;if(Ot(o))return a.$formatCells(t),true;if(Fr(o)){const e=dl(o.anchor.getNode(),e=>We$1(e));if(!We$1(e))return false}return false},so)),a.listenersToRemove.add(o.registerCommand(Re$1,t=>{const n=Qr();if(!Ot(n)||!ln(n,e))return false;const o=n.anchor.getNode(),r=n.focus.getNode();if(!We$1(o)||!We$1(r))return false;if(function(e,t){if(Ot(e)){const n=e.anchor.getNode(),o=e.focus.getNode();if(t&&n&&o){const[e]=wt(t,n,o);return n.getKey()===e[0][0].cell.getKey()&&o.getKey()===e[e.length-1].at(-1).cell.getKey()}}return false}(n,e))return e.setFormat(t),true;const[l,s,i]=wt(e,o,r),c=Math.max(s.startRow+s.cell.__rowSpan-1,i.startRow+i.cell.__rowSpan-1),a=Math.max(s.startColumn+s.cell.__colSpan-1,i.startColumn+i.cell.__colSpan-1),u=Math.min(s.startRow,i.startRow),h=Math.min(s.startColumn,i.startColumn),d=new Set;for(let e=u;e<=c;e++)for(let n=h;n<=a;n++){const o=l[e][n].cell;if(d.has(o))continue;d.add(o),o.setFormat(t);const r=o.getChildren();for(let e=0;e<r.length;e++){const n=r[e];Wi(n)&&!n.isInline()&&n.setFormat(t);}}return true},so)),a.listenersToRemove.add(o.registerCommand(ge$3,t=>{const r=Qr();if(!ln(r,e))return false;if(Ot(r))return a.$clearHighlight(),false;if(Fr(r)){const l=dl(r.anchor.getNode(),e=>We$1(e));if(!We$1(l))return false;if("string"==typeof t){const n=pn(o,r,e);if(n)return mn(n,e,[kr(t)]),true}}return false},so)),l&&a.listenersToRemove.add(o.registerCommand(Fe$2,t=>{const o=Qr();if(!Fr(o)||!o.isCollapsed()||!ln(o,e))return false;const r=un(o.anchor.getNode());return !(null===r||!e.is(hn(r)))&&(gn(t),function(e,t){const o="next"===t?"getNextSibling":"getPreviousSibling",r="next"===t?"getFirstChild":"getLastChild",l=e[o]();if(Wi(l))return l.selectEnd();const s=dl(e,De$1);null===s&&Le$1(247);for(let e=s[o]();De$1(e);e=e[o]()){const t=e[r]();if(Wi(t))return t.selectEnd()}const i=dl(s,Rn);null===i&&Le$1(248);"next"===t?i.selectNext():i.selectPrevious();}(r,t.shiftKey?"previous":"next"),true)},so)),a.listenersToRemove.add(o.registerCommand(Ge$2,t=>e.isSelected(),so)),a.listenersToRemove.add(o.registerCommand(he$3,()=>{const t=Qr();if(!Fr(t)||!t.isCollapsed()||!ln(t,e))return false;const n=pn(o,t,e);return !!n&&(mn(n,e),true)},so)),a}function Xt(e,t){const o=Qr(),r=Zr(),l=e.getAndClearNextFocus();if(null!==l){const{tableKey:t,focusCell:n}=l,r=e.observers.get(t);r||Le$1(335,t);const[s]=r;if(Ot(o)&&o.tableKey===s.tableNodeKey)return (n.x!==s.focusX||n.y!==s.focusY)&&(s.$setFocusCellForSelection(n),true);if(null!==s.anchorCell&&null!==s.anchorCellNodeKey&&n.elem!==s.anchorCell.elem&&null!==s.tableSelection)return s.$setFocusCellForSelection(n,true),true}const s=e.getAndClearShouldCheckSelectionForTable();if(s&&Fr(r)&&Fr(o)&&o.isCollapsed()){const e=Bs(s),t=o.anchor.getNode(),r=e.getFirstChild(),l=un(t);if(null!==l&&De$1(r)){const t=r.getFirstChild();if(We$1(t)&&e.is(dl(l,n=>n.is(e)||n.is(t))))return t.selectStart(),true}}Ot(o)&&function(e,t){const n=Ht(e),o=Zr();if(!t.is(o))return;const r=Bs(t.tableKey),l=Js(n);if(l&&l.anchorNode&&l.focusNode){const n=Go(l.focusNode),o=n&&!r.isParentOf(n),s=Go(l.anchorNode),i=s&&r.isParentOf(s);if(o&&i&&l.rangeCount>0){const n=Gr(l,e);n&&(n.anchor.set(r.getKey(),t.isBackward()?r.getChildrenSize():0,"element"),l.removeAllRanges(),es(n));}}}(t,o),Fr(o)&&function(e,t){const n=Zr(),{anchor:o,focus:r}=e,l=o.getNode(),s=r.getNode(),i=un(l),c=un(s),a=i?hn(i):null,u=c?hn(c):null,h=e.isBackward(),d=i&&c&&a&&u&&a.is(u),f=u&&(!a||a.isParentOf(u)),g=a&&(!u||u.isParentOf(a));if(f){const t=e.clone(),[n]=wt(u,c,c),o=n[0][0].cell,r=n[n.length-1].at(-1).cell;t.focus.set(h?o.getKey():r.getKey(),h?0:r.getChildrenSize(),"element"),es(t);}else if(g){const t=e.clone(),[n]=wt(a,i,i),o=n[0][0].cell,r=n[n.length-1].at(-1).cell;t.anchor.set(h?r.getKey():o.getKey(),h?r.getChildrenSize():0,"element"),es(t);}else if(d){const o=t.observers.get(a.getKey());o||Le$1(335,a.getKey());const[r]=o;if(i.is(c)||(r.$setAnchorCellForSelection(Cn(r,i)),r.$setFocusCellForSelection(Cn(r,c),true)),"touch"===r.pointerType&&r.isSelecting&&e.isCollapsed()&&Fr(n)&&n.isCollapsed()){const e=un(n.anchor.getNode());e&&!e.is(c)&&(r.$setAnchorCellForSelection(Cn(r,e)),r.$setFocusCellForSelection(Cn(r,c),true),r.pointerType=null);}}}(o,e);const i=Array.from(e.observers.entries()).map(([e,[t]])=>({tableNode:Bs(e),tableObserver:t}));for(const{tableNode:e,tableObserver:n}of i)Yt(t,e,n);return false}function Yt(e,t,n){const o=Qr(),r=Zr();o&&!o.is(r)&&(Ot(o)||Ot(r))&&n.tableSelection&&!n.tableSelection.is(r)&&(Ot(o)&&o.tableKey===n.tableNodeKey?n.$updateTableTableSelection(o):!Ot(o)&&Ot(r)&&r.tableKey===n.tableNodeKey&&n.$updateTableTableSelection(null)),n.hasHijackedSelectionStyles&&!t.isSelected()?function(e,t){t.$enableHighlightStyle(),Zt(t.table,t=>{const n=t.elem;t.highlighted=false,an(e,t),n.getAttribute("style")||n.removeAttribute("style");});}(e,n):!n.hasHijackedSelectionStyles&&t.isSelected()&&function(e,t){t.$disableHighlightStyle(),Zt(t.table,t=>{t.highlighted=true,cn(e,t);});}(e,n);}function qt(e){return e[Wt]||null}function jt(e){let t=e;for(;null!=t;){const e=t.nodeName;if("TD"===e||"TH"===e){const e=t._cell;return void 0===e?null:e}t=t.parentNode;}return null}function Vt(e,t){if(!e.contains(t))return null;let n=null;for(let o=t;null!=o;o=o.parentNode){if(o===e)return n;const t=o.nodeName;"TD"!==t&&"TH"!==t||(n=o._cell||null);}return null}function Gt(e,t){const n=[],o={columns:0,domRows:n,rows:0};let r=Lt(e,t).querySelector("tr"),l=0,s=0;for(n.length=0;null!=r;){const e=r.nodeName;if("TD"===e||"TH"===e){const e={elem:r,hasBackgroundColor:""!==r.style.backgroundColor,highlighted:false,x:l,y:s};r._cell=e;let t=n[s];void 0===t&&(t=n[s]=[]),t[l]=e;}else {const e=r.firstChild;if(null!=e){r=e;continue}}const t=r.nextSibling;if(null!=t){l++,r=t;continue}const o=r.parentNode;if(null!=o){const e=o.nextSibling;if(null==e)break;s++,l=0,r=e;}}return o.columns=l+1,o.rows=s+1,o}function Qt(e,t,n){const o=new Set(n?n.getNodes():[]);Zt(t,(t,n)=>{const r=t.elem;o.has(n)?(t.highlighted=true,cn(e,t)):(t.highlighted=false,an(e,t),r.getAttribute("style")||r.removeAttribute("style"));});}function Zt(e,t){const{domRows:n}=e;for(let e=0;e<n.length;e++){const o=n[e];if(o)for(let n=0;n<o.length;n++){const r=o[n];if(!r)continue;const l=Go(r.elem);null!==l&&t(r,l,{x:n,y:e});}}}const en=(e,t,n,o,r)=>{const l="forward"===r;switch(r){case "backward":case "forward":return n!==(l?e.table.columns-1:0)?sn(t.getCellNodeFromCordsOrThrow(n+(l?1:-1),o,e.table),l):o!==(l?e.table.rows-1:0)?sn(t.getCellNodeFromCordsOrThrow(l?0:e.table.columns-1,o+(l?1:-1),e.table),l):l?t.selectNext():t.selectPrevious(),true;case "up":return 0!==o?sn(t.getCellNodeFromCordsOrThrow(n,o-1,e.table),false):t.selectPrevious(),true;case "down":return o!==e.table.rows-1?sn(t.getCellNodeFromCordsOrThrow(n,o+1,e.table),true):t.selectNext(),true;default:return false}};function tn(e,t){let n,o;if(t.startColumn===e.minColumn)n="minColumn";else {if(t.startColumn+t.cell.__colSpan-1!==e.maxColumn)return null;n="maxColumn";}if(t.startRow===e.minRow)o="minRow";else {if(t.startRow+t.cell.__rowSpan-1!==e.maxRow)return null;o="maxRow";}return [n,o]}function nn([e,t]){return ["minColumn"===e?"maxColumn":"minColumn","minRow"===t?"maxRow":"minRow"]}function on(e,t,[n,o]){const r=t[o],l=e[r];void 0===l&&Le$1(250,o,String(r));const s=t[n],i=l[s];return void 0===i&&Le$1(250,n,String(s)),i}function rn(e,t,n,o,r){const l=Nt(t,n,o),s=function(e,t){const{minColumn:n,maxColumn:o,minRow:r,maxRow:l}=t;let s=1,i=1,c=1,a=1;const u=e[r],h=e[l];for(let e=n;e<=o;e++)s=Math.max(s,u[e].cell.__rowSpan),a=Math.max(a,h[e].cell.__rowSpan);for(let t=r;t<=l;t++)i=Math.max(i,e[t][n].cell.__colSpan),c=Math.max(c,e[t][o].cell.__colSpan);return {bottomSpan:a,leftSpan:i,rightSpan:c,topSpan:s}}(t,l),{topSpan:i,leftSpan:c,bottomSpan:a,rightSpan:u}=s,h=function(e,t){const n=tn(e,t);return null===n&&Le$1(249,t.cell.getKey()),n}(l,n),[d,f]=nn(h);let g=l[d],m=l[f];"forward"===r?g+="maxColumn"===d?1:c:"backward"===r?g-="minColumn"===d?1:u:"down"===r?m+="maxRow"===f?1:i:"up"===r&&(m-="minRow"===f?1:a);const p=t[m];if(void 0===p)return false;const C=p[g];if(void 0===C)return false;const[_,S]=function(e,t,n){const o=Nt(e,t,n),r=tn(o,t);if(r)return [on(e,o,r),on(e,o,nn(r))];const l=tn(o,n);if(l)return [on(e,o,nn(l)),on(e,o,l)];const s=["minColumn","minRow"];return [on(e,o,s),on(e,o,nn(s))]}(t,n,C),w=Cn(e,_.cell),b=Cn(e,S.cell);return e.$setAnchorCellForSelection(w),e.$setFocusCellForSelection(b,true),true}function ln(e,t){if(Fr(e)||Ot(e)){const n=t.isParentOf(e.anchor.getNode()),o=t.isParentOf(e.focus.getNode());return n&&o}return false}function sn(e,t){t?e.selectStart():e.selectEnd();}function cn(t,n){const o=n.elem,r=t._config.theme;We$1(Go(o))||Le$1(131),mc(o,r.tableCellSelected);}function an(e,t){const n=t.elem;We$1(Go(n))||Le$1(131);const r=e._config.theme;xc(n,r.tableCellSelected);}function un(e){const t=dl(e,We$1);return We$1(t)?t:null}function hn(e){const t=dl(e,Rn);return Rn(t)?t:null}function dn(e,t,o,r,l,s,i){const c=ql(o.focus,l?"previous":"next");if(ic(c))return false;let a=c;for(const e of Rl(c).iterNodeCarets("shadowRoot")){if(!Tl(e)||!Wi(e.origin))return false;a=e;}const u=a.getParentAtCaret();if(!We$1(u))return false;const h=u,d=function(e){for(const t of Rl(e).iterNodeCarets("root")){const{origin:n}=t;if(We$1(n)){if(Nl(t))return Pl(n,e.direction)}else if(!De$1(n))break}return null}(Ol(h,a.direction)),f=dl(h,Rn);if(!f||!f.is(s))return false;const g=e.getElementByKey(h.getKey()),m=jt(g);if(!g||!m)return false;const p=xn(e,f);if(i.table=p,d)if("extend"===r){const t=jt(e.getElementByKey(d.origin.getKey()));if(!t)return false;i.$setAnchorCellForSelection(m),i.$setFocusCellForSelection(t,true);}else {const e=rc(d);Hl(o.anchor,e),Hl(o.focus,e);}else if("extend"===r)i.$setAnchorCellForSelection(m),i.$setFocusCellForSelection(m,true);else {const e=function(e){const t=Ll(e);return Nl(t)?rc(t):e}(Ol(f,c.direction));Hl(o.anchor,e),Hl(o.focus,e);}return gn(t),true}function fn(e,t,o,r,l,s){if(("up"===o||"down"===o)&&function(e){const t=e.getRootElement();if(!t)return false;return t.hasAttribute("aria-controls")&&"typeahead-menu"===t.getAttribute("aria-controls")}(e))return false;const i=Qr();if(!ln(i,r)){if(Fr(i)){if("backward"===o){if(i.focus.offset>0)return false;const e=function(e){for(let t=e,n=e;null!==n;t=n,n=n.getParent())if(Wi(n)){if(n!==t&&n.getFirstChild()!==t)return null;if(!n.isInline())return n}return null}(i.focus.getNode());if(!e)return false;const n=e.getPreviousSibling();return !!Rn(n)&&(gn(t),t.shiftKey?i.focus.set(n.getParentOrThrow().getKey(),n.getIndexWithinParent(),"element"):n.selectEnd(),true)}if(t.shiftKey&&("up"===o||"down"===o)){const e=i.focus.getNode();if(!i.isCollapsed()&&("up"===o&&!i.isBackward()||"down"===o&&i.isBackward())){let l=dl(e,e=>Rn(e));if(We$1(l)&&(l=dl(l,Rn)),l!==r)return false;if(!l)return false;const s="down"===o?l.getNextSibling():l.getPreviousSibling();if(!s)return false;let c=0;"up"===o&&Wi(s)&&(c=s.getChildrenSize());let a=s;if("up"===o&&Wi(s)){const e=s.getLastChild();a=e||s,c=Tr(a)?a.getTextContentSize():0;}const u=i.clone();return u.focus.set(a.getKey(),c,Tr(a)?"text":"element"),es(u),gn(t),true}if(Is(e)){const e="up"===o?i.getNodes()[i.getNodes().length-1]:i.getNodes()[0];if(e){if(null!==Bt(r,e)){const e=r.getFirstDescendant(),t=r.getLastDescendant();if(!e||!t)return false;const[n]=yt(e),[o]=yt(t),s=r.getCordsFromCellNode(n,l.table),i=r.getCordsFromCellNode(o,l.table),c=r.getDOMCellFromCordsOrThrow(s.x,s.y,l.table),a=r.getDOMCellFromCordsOrThrow(i.x,i.y,l.table);return l.$setAnchorCellForSelection(c),l.$setFocusCellForSelection(a,true),true}}return false}{let r=dl(e,e=>Wi(e)&&!e.isInline());if(We$1(r)&&(r=dl(r,Rn)),!r)return false;const s="down"===o?r.getNextSibling():r.getPreviousSibling();if(Rn(s)&&l.tableNodeKey===s.getKey()){const e=s.getFirstDescendant(),n=s.getLastDescendant();if(!e||!n)return false;const[r]=yt(e),[l]=yt(n),c=i.clone();return c.focus.set(("up"===o?r:l).getKey(),"up"===o?0:l.getChildrenSize(),"element"),gn(t),es(c),true}}}}return "down"===o&&yn(e)&&s.setShouldCheckSelectionForTable(r.getKey()),false}if(Fr(i)){if("backward"===o||"forward"===o){return dn(e,t,i,t.shiftKey?"extend":"move","backward"===o,r,l)}if(i.isCollapsed()){const{anchor:c,focus:a}=i,u=dl(c.getNode(),We$1),h=dl(a.getNode(),We$1);if(!We$1(u)||!u.is(h))return false;const d=hn(u);if(d!==r&&null!=d){const n=Lt(d,e.getElementByKey(d.getKey()));if(null!=n)return l.table=Gt(d,n),fn(e,t,o,d,l,s)}const f=e.getElementByKey(u.__key),g=e.getElementByKey(c.key);if(null==g||null==f)return false;let m;if("element"===c.type)m=g.getBoundingClientRect();else {const t=Js(Ht(e));if(null===t||0===t.rangeCount)return false;m=t.getRangeAt(0).getBoundingClientRect();}const p="up"===o?u.getFirstChild():u.getLastChild();if(null==p)return false;const C=e.getElementByKey(p.__key);if(null==C)return false;const _=C.getBoundingClientRect();if("up"===o?_.top>m.top-m.height:m.bottom+m.height>_.bottom){gn(t);const e=r.getCordsFromCellNode(u,l.table);if(!t.shiftKey)return en(l,r,e.x,e.y,o);{const t=r.getDOMCellFromCordsOrThrow(e.x,e.y,l.table);l.$setAnchorCellForSelection(t),l.$setFocusCellForSelection(t,true);}return true}}}else if(Ot(i)){const{anchor:s,focus:c}=i,a=dl(s.getNode(),We$1),u=dl(c.getNode(),We$1),[h]=i.getNodes();Rn(h)||Le$1(251);const d=Lt(h,e.getElementByKey(h.getKey()));if(!We$1(a)||!We$1(u)||!Rn(h)||null==d)return false;l.$updateTableTableSelection(i);const f=Gt(h,d),g=r.getCordsFromCellNode(a,f),m=r.getDOMCellFromCordsOrThrow(g.x,g.y,f);if(l.$setAnchorCellForSelection(m),gn(t),t.shiftKey){const[e,t,n]=wt(r,a,u);return rn(l,e,t,n,o)}return u.selectEnd(),true}return false}function gn(e){e.preventDefault(),e.stopImmediatePropagation(),e.stopPropagation();}function mn(e,t,n){const o=eo();"first"===e?t.insertBefore(o):t.insertAfter(o),o.append(...n||[]),o.selectEnd();}function pn(e,t,o){const r=o.getParent();if(!r)return;const l=Js(Ht(e));if(!l)return;const s=l.anchorNode,i=e.getElementByKey(r.getKey()),c=Lt(o,e.getElementByKey(o.getKey()));if(!s||!i||!c||!i.contains(s)||c.contains(s))return;const a=dl(t.anchor.getNode(),e=>We$1(e));if(!a)return;const u=dl(a,e=>Rn(e));if(!Rn(u)||!u.is(o))return;const[h,d]=wt(o,a,a),f=h[0][0],g=h[h.length-1][h[0].length-1],{startRow:m,startColumn:p}=d,C=m===f.startRow&&p===f.startColumn,_=m===g.startRow&&p===g.startColumn;return C?"first":_?"last":void 0}function Cn(e,t){const{tableNode:n}=e.$lookup(),o=n.getCordsFromCellNode(t,e.table);return n.getDOMCellFromCordsOrThrow(o.x,o.y,e.table)}function _n(e,t,n){return Bt(e,Go(t,n))}function Sn(e,t,n){const o=e.querySelector("colgroup");if(!o)return;const r=[];for(let e=0;e<t;e++){const t=document.createElement("col"),o=n&&n[e];o&&(t.style.width=`${o}px`),r.push(t);}o.replaceChildren(...r);}function wn(t,n,r){if(!n.theme.tableAlignment)return;const l=[],s=[];for(const e of ["center","right"]){const t=n.theme.tableAlignment[e];t&&(e===r?s:l).push(t);}xc(t,...l),mc(t,...s);}const bn=new WeakSet;function yn(e=Zs()){return bn.has(e)}function Nn(e,t){bn.add(e);}class vn extends Bi{__rowStriping;__frozenColumnCount;__frozenRowCount;__colWidths;static getType(){return "table"}getColWidths(){return this.getLatest().__colWidths}setColWidths(e){const t=this.getWritable();return t.__colWidths=e,t}static clone(e){return new vn(e.__key)}afterCloneFrom(e){super.afterCloneFrom(e),this.__colWidths=e.__colWidths,this.__rowStriping=e.__rowStriping,this.__frozenColumnCount=e.__frozenColumnCount,this.__frozenRowCount=e.__frozenRowCount;}static importDOM(){return {table:e=>({conversion:Tn,priority:1})}}static importJSON(e){return Fn().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setRowStriping(e.rowStriping||false).setFrozenColumns(e.frozenColumnCount||0).setFrozenRows(e.frozenRowCount||0).setColWidths(e.colWidths)}constructor(e){super(e),this.__rowStriping=false,this.__frozenColumnCount=0,this.__frozenRowCount=0,this.__colWidths=void 0;}exportJSON(){return {...super.exportJSON(),colWidths:this.getColWidths(),frozenColumnCount:this.__frozenColumnCount?this.__frozenColumnCount:void 0,frozenRowCount:this.__frozenRowCount?this.__frozenRowCount:void 0,rowStriping:this.__rowStriping?this.__rowStriping:void 0}}extractWithChild(e,t,n){return "html"===n}getDOMSlot(e){const t=zt(e)?e:e.querySelector("table");return zt(t)||Le$1(229),super.getDOMSlot(e).withElement(t).withAfter(t.querySelector("colgroup"))}createDOM(t,n){const o=document.createElement("table");this.__style&&nr(o.style,this.__style);const r=document.createElement("colgroup");if(o.appendChild(r),ll(r),mc(o,t.theme.table),this.updateTableElement(null,o,t),yn(n)){const n=document.createElement("div"),r=t.theme.tableScrollableWrapper;return r?mc(n,r):n.style.overflowX="auto",n.appendChild(o),this.updateTableWrapper(null,n,o,t),n}return o}updateTableWrapper(t,n,r,l){this.__frozenColumnCount!==(t?t.__frozenColumnCount:0)&&function(t,n,r,l){l>0?(mc(t,r.theme.tableFrozenColumn),n.setAttribute("data-lexical-frozen-column","true")):(xc(t,r.theme.tableFrozenColumn),n.removeAttribute("data-lexical-frozen-column"));}(n,r,l,this.__frozenColumnCount),this.__frozenRowCount!==(t?t.__frozenRowCount:0)&&function(t,n,r,l){l>0?(mc(t,r.theme.tableFrozenRow),n.setAttribute("data-lexical-frozen-row","true")):(xc(t,r.theme.tableFrozenRow),n.removeAttribute("data-lexical-frozen-row"));}(n,r,l,this.__frozenRowCount);}updateTableElement(t,n,r){this.__style!==(t?t.__style:"")&&nr(n.style,this.__style,t?t.__style:""),this.__rowStriping!==(!!t&&t.__rowStriping)&&function(t,n,r){r?(mc(t,n.theme.tableRowStriping),t.setAttribute("data-lexical-row-striping","true")):(xc(t,n.theme.tableRowStriping),t.removeAttribute("data-lexical-row-striping"));}(n,r,this.__rowStriping);const l=t?t.getColumnCount():0,s=t?t.__colWidths:void 0;this.getColumnCount()===l&&this.getColWidths()===s||Sn(n,this.getColumnCount(),this.getColWidths()),wn(n,r,this.getFormatType());}updateDOM(e,t,n){const o=Lt(this,t);return t===o===yn()||(Ys(r=t)&&"DIV"===r.nodeName&&this.updateTableWrapper(e,t,o,n),this.updateTableElement(e,o,n),false);var r;}scaleDOMColWidths(e,t){const n=this.getColWidths();if(!n)return;Sn(Lt(this,e),this.getColumnCount(),n.map(e=>e*t));}exportDOM(e){const t=super.exportDOM(e),{element:n}=t;return {after:n=>{if(t.after&&(n=t.after(n)),!zt(n)&&Ys(n)&&(n=n.querySelector("table")),!zt(n))return null;wn(n,e._config,this.getFormatType());const[o]=bt(this,null,null),r=new Map;for(const e of o)for(const t of e){const e=t.cell.getKey();r.has(e)||r.set(e,{colSpan:t.cell.getColSpan(),startColumn:t.startColumn});}const s=new Set;for(const e of n.querySelectorAll(":scope > tr > [data-temporary-table-cell-lexical-key]")){const t=e.getAttribute("data-temporary-table-cell-lexical-key");if(t){const n=r.get(t);if(e.removeAttribute("data-temporary-table-cell-lexical-key"),n){r.delete(t);for(let e=0;e<n.colSpan;e++)s.add(e+n.startColumn);}}}const i=n.querySelector(":scope > colgroup");if(i){const e=Array.from(n.querySelectorAll(":scope > colgroup > col")).filter((e,t)=>s.has(t));i.replaceChildren(...e);}const c=n.querySelectorAll(":scope > tr");if(c.length>0){const e=document.createElement("tbody");for(const t of c)e.appendChild(t);n.append(e);}return n},element:!zt(n)&&Ys(n)?n.querySelector("table"):n}}canBeEmpty(){return false}isShadowRoot(){return true}getCordsFromCellNode(e,t){const{rows:n,domRows:o}=t;for(let t=0;t<n;t++){const n=o[t];if(null!=n)for(let o=0;o<n.length;o++){const r=n[o];if(null==r)continue;const{elem:l}=r,s=_n(this,l);if(null!==s&&e.is(s))return {x:o,y:t}}}throw new Error("Cell not found in table.")}getDOMCellFromCords(e,t,n){const{domRows:o}=n,r=o[t];if(null==r)return null;const l=r[e<r.length?e:r.length-1];return null==l?null:l}getDOMCellFromCordsOrThrow(e,t,n){const o=this.getDOMCellFromCords(e,t,n);if(!o)throw new Error("Cell not found at cords.");return o}getCellNodeFromCords(e,t,n){const o=this.getDOMCellFromCords(e,t,n);if(null==o)return null;const r=Go(o.elem);return We$1(r)?r:null}getCellNodeFromCordsOrThrow(e,t,n){const o=this.getCellNodeFromCords(e,t,n);if(!o)throw new Error("Node at cords not TableCellNode.");return o}getRowStriping(){return Boolean(this.getLatest().__rowStriping)}setRowStriping(e){const t=this.getWritable();return t.__rowStriping=e,t}setFrozenColumns(e){const t=this.getWritable();return t.__frozenColumnCount=e,t}getFrozenColumns(){return this.getLatest().__frozenColumnCount}setFrozenRows(e){const t=this.getWritable();return t.__frozenRowCount=e,t}getFrozenRows(){return this.getLatest().__frozenRowCount}canSelectBefore(){return true}canIndent(){return false}getColumnCount(){const e=this.getFirstChild();if(!e)return 0;let t=0;return e.getChildren().forEach(e=>{We$1(e)&&(t+=e.getColSpan());}),t}}function xn(e,t){const n=e.getElementByKey(t.getKey());return null===n&&Le$1(230),Gt(t,n)}function Tn(e){const n=Fn();e.hasAttribute("data-lexical-row-striping")&&n.setRowStriping(true),e.hasAttribute("data-lexical-frozen-column")&&n.setFrozenColumns(1),e.hasAttribute("data-lexical-frozen-row")&&n.setFrozenRows(1);const o=e.querySelector(":scope > colgroup");if(o){let e=[];for(const t of o.querySelectorAll(":scope > col")){let n=t.style.width||"";if(!Ke$1.test(n)&&(n=t.getAttribute("width")||"",!/^\d+$/.test(n))){e=void 0;break}e.push(parseFloat(n));}e&&n.setColWidths(e);}return {after:e=>Ht$3(e,De$1),node:n}}function Fn(){return zs(new vn)}function Rn(e){return e instanceof vn}function On(e){De$1(e.getParent())?e.isEmpty()&&e.append(eo()):e.remove();}function Kn(e){Rn(e.getParent())?Ot$3(e,We$1):e.remove();}function An(e){Ot$3(e,De$1);const[t]=bt(e,null,null),n=t.reduce((e,t)=>Math.max(e,t.length),0),o=e.getChildren();for(let e=0;e<t.length;++e){const r=o[e];if(!r)continue;De$1(r)||Le$1(254,r.constructor.name,r.getType());const l=t[e].reduce((e,t)=>t?1+e:e,0);if(l!==n)for(let e=l;e<n;++e){const e=$e$1();e.append(eo()),r.append(e);}}const r=e.getColWidths(),l=e.getColumnCount();if(r&&r.length!==l){let t;if(l<r.length)t=r.slice(0,l);else if(r.length>0){const e=r[r.length-1];t=[...r,...Array(l-r.length).fill(e)];}e.setColWidths(t);}}function En(e){if(e.detail<3||!qs(e.target))return false;const t=Go(e.target);if(null===t)return false;const o=dl(t,e=>Wi(e)&&!e.isInline());if(null===o)return false;return !!We$1(o.getParent())&&(o.select(0),true)}function kn(){const e=Qr();if(!Fr(e))return false;const t=hn(e.anchor.getNode());if(null===t)return false;const n=Zo();if(!n.is(t.getParent())||1!==n.getChildrenSize())return false;const[o]=bt(t,null,null);if(0===o.length||0===o[0].length)return false;const r=o[0][0];if(!r||!r.cell)return false;const l=o[o.length-1],s=l[l.length-1];if(!s||!s.cell)return false;const i=At(t,r.cell,s.cell);return es(i),true}function $n(e,t=true){const n=new Mt,o=(o,r,l)=>{const s=Lt(o,l),i=Jt(o,s,e,t,n);n.observers.set(r,[i,s]);};return Cc(Ut(e,n),e.registerCommand(ie$4,()=>Xt(n,e),so),e.registerMutationListener(vn,t=>{e.getEditorState().read(()=>{for(const[e,r]of t){const t=n.observers.get(e);if("created"===r||"updated"===r){const{tableNode:r,tableElement:l}=kt(e);void 0===t?o(r,e,l):l!==t[1]&&(t[0].removeListeners(),n.observers.delete(e),o(r,e,l));}else "destroyed"===r&&void 0!==t&&(t[0].removeListeners(),n.observers.delete(e));}},{editor:e});},{skipInitialization:false}),()=>{for(const[,[e]]of n.observers)e.removeListeners();})}function Wn(e,t){e.hasNodes([vn])||Le$1(255);const{hasNestedTables:o=ft$1(false)}={};return Cc(e.registerCommand(ze$1,e=>function({rows:e,columns:t,includeHeaders:n},o){const r=Qr()||Zr();if(!r||!Fr(r))return false;if(!o&&hn(r.anchor.getNode()))return false;const l=Xe$1(Number(e),Number(t),n);Pt$3(l);const s=l.getFirstDescendant();return Tr(s)&&s.select(),true}(e,o.peek()),ro),e.registerCommand(oe$6,(t,r)=>e===r&&function(e,t){const{nodes:o,selection:r}=e;if(!o.some(e=>Rn(e)||pt$2(e).some(e=>Rn(e.node))))return false;const l=Ot(r),s=Fr(r);if(!(s&&null!==dl(r.anchor.getNode(),e=>We$1(e))&&null!==dl(r.focus.getNode(),e=>We$1(e))||l))return false;if(1===o.length&&Rn(o[0]))return function(e,t){const o=t.getStartEndPoints(),r=Ot(t);if(null===o)return false;const[l,s]=o,[i,c,a]=yt(l),u=dl(s.getNode(),e=>We$1(e));if(!(We$1(i)&&We$1(u)&&De$1(c)&&Rn(a)))return false;const[h,d,f]=wt(a,i,u),[m]=bt(e,null,null),C=h.length,_=C>0?h[0].length:0;let S=d.startRow,w=d.startColumn,b=m.length,y=b>0?m[0].length:0;if(r){const e=Nt(h,d,f),t=e.maxRow-e.minRow+1,n=e.maxColumn-e.minColumn+1;S=e.minRow,w=e.minColumn,b=Math.min(b,t),y=Math.min(y,n);}let N=false;const v=Math.min(C,S+b)-1,x=Math.min(_,w+y)-1,T=new Set;for(let e=S;e<=v;e++)for(let t=w;t<=x;t++){const n=h[e][t];T.has(n.cell.getKey())||(1===n.cell.__rowSpan&&1===n.cell.__colSpan||(St(n.cell),T.add(n.cell.getKey()),N=true));}let[F]=bt(a.getWritable(),null,null);const R=b-C+S;for(let e=0;e<R;e++){rt(F[C-1][0].cell);}const O=y-_+w;for(let e=0;e<O;e++){ct(F[0][_-1].cell,true,false);}[F]=bt(a.getWritable(),null,null);for(let e=S;e<S+b;e++)for(let t=w;t<w+y;t++){const n=e-S,o=t-w,r=m[n][o];if(r.startRow!==n||r.startColumn!==o)continue;const l=r.cell;if(1!==l.__rowSpan||1!==l.__colSpan){const n=[],o=Math.min(e+l.__rowSpan,S+b)-1,r=Math.min(t+l.__colSpan,w+y)-1;for(let l=e;l<=o;l++)for(let e=t;e<=r;e++){const t=F[l][e];n.push(t.cell);}pt(n),N=true;}const{cell:s}=F[e][t],i=l.getBackgroundColor();null!=i&&s.setBackgroundColor(i);const c=s.getChildren();l.getChildren().forEach(e=>{if(Tr(e)){eo().append(e),s.append(e);}else s.append(e);}),c.forEach(e=>e.remove());}if(r&&N){const[e]=bt(a.getWritable(),null,null);e[d.startRow][d.startColumn].cell.selectEnd();}return true}(o[0],r);if(s&&t.peek()&&!function(e){if(Ot(e)&&!e.focus.getNode().is(e.anchor.getNode()))return true;if(Fr(e)&&We$1(e.anchor.getNode())&&!e.anchor.getNode().is(e.focus.getNode()))return true;return false}(r))return false;return true}(t,o),ro),e.registerCommand(Ue$2,kn,io),e.registerCommand(se$5,En,ro),e.registerNodeTransform(vn,An),e.registerNodeTransform(He$1,Kn),e.registerNodeTransform(Ee$1,On))}
11355
11839
 
11356
- styleResolverRoot().appendChild(fragment);
11840
+ // Partition a stretch of text into consecutive { start, end, range } segments,
11841
+ // where offsets are relative to the text and range is the covering source
11842
+ // range — expressed in outer coordinates as { start, end, ... } — or null for
11843
+ // the stretches no range covers. Ranges must be sorted and non-overlapping.
11844
+ function segmentTextByRanges(text, textStart, ranges) {
11845
+ const segments = [];
11846
+ let cursor = 0;
11357
11847
 
11358
- const computed = elements.map(element =>
11359
- window.getComputedStyle(element).getPropertyValue(property)
11360
- );
11848
+ for (const range of ranges) {
11849
+ const from = Math.max(range.start - textStart, cursor);
11850
+ const to = Math.min(range.end - textStart, text.length);
11361
11851
 
11362
- elements.forEach(element => element.remove());
11363
- return computed
11852
+ if (from < to) {
11853
+ if (from > cursor) {
11854
+ segments.push({ start: cursor, end: from, range: null });
11855
+ }
11856
+ segments.push({ start: from, end: to, range });
11857
+ cursor = to;
11858
+ }
11859
+ }
11860
+
11861
+ if (cursor < text.length) {
11862
+ segments.push({ start: cursor, end: text.length, range: null });
11863
+ }
11864
+
11865
+ return segments
11364
11866
  }
11365
11867
 
11366
11868
  const TOGGLE_HIGHLIGHT_COMMAND = re$5();
@@ -11645,11 +12147,15 @@ function $extractHighlightRangesFromCodeNode(codeNode) {
11645
12147
 
11646
12148
  function buildCanonicalizers(config) {
11647
12149
  return [
11648
- new StyleCanonicalizer("color", [ ...config.buttons.color, ...config.permit.color ]),
11649
- new StyleCanonicalizer("background-color", [ ...config.buttons["background-color"], ...config.permit["background-color"] ])
12150
+ new StyleCanonicalizer("color", [ ...colorValues(config.buttons.color), ...config.permit.color ]),
12151
+ new StyleCanonicalizer("background-color", [ ...colorValues(config.buttons["background-color"]), ...config.permit["background-color"] ])
11650
12152
  ]
11651
12153
  }
11652
12154
 
12155
+ function colorValues(buttons) {
12156
+ return normalizeColorButtons(buttons).map((button) => button.value)
12157
+ }
12158
+
11653
12159
  function $toggleSelectionStyles(editor, styles) {
11654
12160
  const selection = Qr();
11655
12161
  if (!Fr(selection)) return
@@ -12588,29 +13094,25 @@ class Selection {
12588
13094
  }, io),
12589
13095
 
12590
13096
  this.editor.registerCommand(ie$4, () => {
12591
- this.#preserveFocusOfOtherFields();
13097
+ this.#preserveFocusOutsideEditor();
12592
13098
  return false
12593
13099
  }, lo)
12594
13100
  );
12595
13101
  }
12596
13102
 
12597
- // Firefox (152+) keeps window.getSelection() anchored inside the editor after focus
12598
- // moves to another field, and fires document selectionchange for every keystroke
12599
- // typed there. Lexical reads that stale selection, reconciles, and pulls focus back
12600
- // into the editor — stealing it mid-typing. When another text-entry field owns focus,
12601
- // tag the update so Lexical leaves the DOM selection (and with it, focus) alone.
12602
- #preserveFocusOfOtherFields() {
12603
- if (this.#anotherFieldIsFocused) {
13103
+ // Selection changes can arrive after Tab moves focus to a toolbar or another field.
13104
+ // Reconciling that stale selection would pull focus back into the editor.
13105
+ #preserveFocusOutsideEditor() {
13106
+ if (this.#isAnotherElementFocused) {
12604
13107
  Os(qn);
12605
13108
  }
12606
13109
  }
12607
13110
 
12608
- get #anotherFieldIsFocused() {
13111
+ get #isAnotherElementFocused() {
12609
13112
  const rootElement = this.editor.getRootElement();
12610
13113
  const activeElement = rootElement?.ownerDocument.activeElement;
12611
13114
 
12612
- return activeElement && !rootElement.contains(activeElement) &&
12613
- (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.isContentEditable)
13115
+ return activeElement && activeElement !== rootElement.ownerDocument.body && !rootElement.contains(activeElement)
12614
13116
  }
12615
13117
 
12616
13118
  #listenForNodeSelections() {
@@ -13140,243 +13642,71 @@ class Selection {
13140
13642
 
13141
13643
  // Get a reliable bounding rect for the first or last character in a DOM
13142
13644
  // element by creating a non-collapsed range around it.
13143
- #getEdgeCharRect(element, edge) {
13144
- const walker = document.createTreeWalker(element, 4 /* NodeFilter.SHOW_TEXT */);
13145
- let textNode;
13146
-
13147
- if (edge === "first") {
13148
- textNode = walker.nextNode();
13149
- } else {
13150
- while (walker.nextNode()) textNode = walker.currentNode;
13151
- }
13152
-
13153
- if (!textNode || textNode.length === 0) return null
13154
-
13155
- const range = document.createRange();
13156
- if (edge === "first") {
13157
- range.setStart(textNode, 0);
13158
- range.setEnd(textNode, 1);
13159
- } else {
13160
- range.setStart(textNode, textNode.length - 1);
13161
- range.setEnd(textNode, textNode.length);
13162
- }
13163
-
13164
- return range.getBoundingClientRect()
13165
- }
13166
- }
13167
-
13168
- class EditorConfiguration {
13169
- #editorElement
13170
- #config
13171
-
13172
- constructor(editorElement) {
13173
- this.#editorElement = editorElement;
13174
- this.#config = new Configuration(
13175
- Lexxy.presets.get("default"),
13176
- Lexxy.presets.get(editorElement.preset),
13177
- this.#overrides
13178
- );
13179
- }
13180
-
13181
- get(path) {
13182
- return this.#config.get(path)
13183
- }
13184
-
13185
- get #overrides() {
13186
- const overrides = {};
13187
- for (const option of this.#defaultOptions) {
13188
- const attribute = dasherize(option);
13189
- if (this.#editorElement.hasAttribute(attribute)) {
13190
- overrides[option] = this.#parseAttribute(attribute);
13191
- }
13192
- }
13193
- return overrides
13194
- }
13195
-
13196
- get #defaultOptions() {
13197
- return Object.keys(Lexxy.presets.get("default"))
13198
- }
13199
-
13200
- #parseAttribute(attribute) {
13201
- const value = this.#editorElement.getAttribute(attribute);
13202
- try {
13203
- return JSON.parse(value)
13204
- } catch {
13205
- return value
13206
- }
13207
- }
13208
- }
13209
-
13210
- class ImageGalleryNode extends Bi {
13211
- $config() {
13212
- return this.config("image_gallery", {
13213
- extends: Bi,
13214
- })
13215
- }
13216
-
13217
- static transform() {
13218
- return (gallery) => {
13219
- gallery.unwrapEmptyNode()
13220
- || gallery.replaceWithSingularChild()
13221
- || gallery.splitAroundInvalidChild();
13222
- }
13223
- }
13224
-
13225
- static importDOM() {
13226
- return {
13227
- div: (element) => {
13228
- if (!this.#isGalleryElement(element)) return null
13229
-
13230
- return {
13231
- conversion: () => {
13232
- return {
13233
- node: $createImageGalleryNode()
13234
- }
13235
- },
13236
- priority: 2
13237
- }
13238
- }
13239
- }
13240
- }
13241
-
13242
- static canCollapseWith(node) {
13243
- return $isImageGalleryNode(node) || this.isValidChild(node)
13244
- }
13245
-
13246
- static isValidChild(node) {
13247
- return $isActionTextAttachmentNode(node) && node.isPreviewableImage
13248
- }
13249
-
13250
- static #isGalleryElement(element) {
13251
- const attachmentChildren = element.querySelectorAll(`:scope > :is(${this.#attachmentTags.join()})`);
13252
- return element.textContent.trim() === ""
13253
- && attachmentChildren.length > 0
13254
- && element.children.length === attachmentChildren.length
13255
- }
13256
-
13257
- static get #attachmentTags() {
13258
- return Object.keys(ActionTextAttachmentNode.importDOM())
13259
- }
13260
-
13261
- createDOM() {
13262
- const div = document.createElement("div");
13263
- div.className = this.#galleryClassNames;
13264
- return div
13265
- }
13266
-
13267
- updateDOM(_prevNode, dom) {
13268
- dom.className = this.#galleryClassNames;
13269
- return false
13270
- }
13271
-
13272
- canBeEmpty() {
13273
- // Return `true` to conform to `$isBlock(node)`
13274
- // We clean-up empty galleries with a transform
13275
- return true
13276
- }
13277
-
13278
- collapseAtStart(_selection) {
13279
- return true
13280
- }
13281
-
13282
- insertNewAfter(selection, restoreSelection) {
13283
- const selectionBeforeLastChild = selection.anchor.getNode().is(this) && selection.anchor.offset == this.getChildrenSize() - 1;
13284
- if (selectionBeforeLastChild) {
13285
- const paragraph = eo();
13286
- this.insertAfter(paragraph, false);
13287
- paragraph.insertAfter(this.getLastChild(), false);
13288
- paragraph.selectEnd();
13289
-
13290
- // return null as selection has been managed
13291
- return null
13292
- }
13293
-
13294
- const newNode = $createImageGalleryNode();
13295
- this.insertAfter(newNode, restoreSelection);
13296
- return newNode
13297
- }
13298
-
13299
- getImageAttachments() {
13300
- const children = this.getChildren();
13301
- return children.filter($isActionTextAttachmentNode)
13302
- }
13303
-
13304
- exportDOM() {
13305
- const div = document.createElement("div");
13306
- div.className = this.#galleryClassNames;
13307
- return { element: div }
13308
- }
13309
-
13310
- collapseWith(node, backwards) {
13311
- if (!ImageGalleryNode.canCollapseWith(node)) return false
13312
-
13313
- if (backwards) {
13314
- $t$2(this, node);
13315
- } else {
13316
- this.append(node);
13317
- }
13318
-
13319
- Ot$3(this, ImageGalleryNode.isValidChild);
13320
-
13321
- return true
13322
- }
13323
-
13324
- unwrapEmptyNode() {
13325
- if (this.isEmpty()) {
13326
- const paragraph = eo();
13327
- return this.replace(paragraph)
13328
- }
13329
- }
13330
-
13331
- replaceWithSingularChild() {
13332
- if (this.#hasSingularChild) {
13333
- const child = this.getFirstChild();
13334
- return this.replace($makeSafeForRoot(child))
13335
- }
13336
- }
13337
-
13338
- splitAroundInvalidChild() {
13339
- for (const child of jt$2(this)) {
13340
- if (ImageGalleryNode.isValidChild(child)) continue
13645
+ #getEdgeCharRect(element, edge) {
13646
+ const walker = document.createTreeWalker(element, 4 /* NodeFilter.SHOW_TEXT */);
13647
+ let textNode;
13341
13648
 
13342
- const poppedNode = $makeSafeForRoot(child);
13343
- const [ topGallery, secondGallery ] = this.splitAtIndex(poppedNode.getIndexWithinParent());
13344
- topGallery.insertAfter(poppedNode);
13345
- poppedNode.selectEnd();
13649
+ if (edge === "first") {
13650
+ textNode = walker.nextNode();
13651
+ } else {
13652
+ while (walker.nextNode()) textNode = walker.currentNode;
13653
+ }
13346
13654
 
13347
- // remove an empty gallery rather than let it unwrap to a paragraph
13348
- if (secondGallery.isEmpty()) secondGallery.remove();
13655
+ if (!textNode || textNode.length === 0) return null
13349
13656
 
13350
- break
13657
+ const range = document.createRange();
13658
+ if (edge === "first") {
13659
+ range.setStart(textNode, 0);
13660
+ range.setEnd(textNode, 1);
13661
+ } else {
13662
+ range.setStart(textNode, textNode.length - 1);
13663
+ range.setEnd(textNode, textNode.length);
13351
13664
  }
13352
- }
13353
13665
 
13354
- splitAtIndex(index) {
13355
- return Us(this, index)
13666
+ return range.getBoundingClientRect()
13356
13667
  }
13668
+ }
13357
13669
 
13358
- get #hasSingularChild() {
13359
- return this.getChildrenSize() === 1
13360
- }
13670
+ class EditorConfiguration {
13671
+ #editorElement
13672
+ #config
13361
13673
 
13362
- get #galleryClassNames() {
13363
- return `attachment-gallery attachment-gallery--${this.getChildrenSize()}`
13674
+ constructor(editorElement) {
13675
+ this.#editorElement = editorElement;
13676
+ this.#config = new Configuration(
13677
+ Lexxy.presets.get("default"),
13678
+ Lexxy.presets.get(editorElement.preset),
13679
+ this.#overrides
13680
+ );
13364
13681
  }
13365
- }
13366
13682
 
13367
- function $createImageGalleryNode() {
13368
- return new ImageGalleryNode()
13369
- }
13683
+ get(path) {
13684
+ return this.#config.get(path)
13685
+ }
13370
13686
 
13371
- function $isImageGalleryNode(node) {
13372
- return node instanceof ImageGalleryNode
13373
- }
13687
+ get #overrides() {
13688
+ const overrides = {};
13689
+ for (const option of this.#defaultOptions) {
13690
+ const attribute = dasherize(option);
13691
+ if (this.#editorElement.hasAttribute(attribute)) {
13692
+ overrides[option] = this.#parseAttribute(attribute);
13693
+ }
13694
+ }
13695
+ return overrides
13696
+ }
13374
13697
 
13375
- function $findOrCreateGalleryForImage(node) {
13376
- if (!ImageGalleryNode.canCollapseWith(node)) return null
13698
+ get #defaultOptions() {
13699
+ return Object.keys(Lexxy.presets.get("default"))
13700
+ }
13377
13701
 
13378
- const existingGallery = At$2(node, ImageGalleryNode);
13379
- return existingGallery ?? Tt$4(node, $createImageGalleryNode)
13702
+ #parseAttribute(attribute) {
13703
+ const value = this.#editorElement.getAttribute(attribute);
13704
+ try {
13705
+ return JSON.parse(value)
13706
+ } catch {
13707
+ return value
13708
+ }
13709
+ }
13380
13710
  }
13381
13711
 
13382
13712
  class Uploader {
@@ -13586,6 +13916,11 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
13586
13916
  updateDOM(prevNode, dom) {
13587
13917
  if (this.uploadError !== prevNode.uploadError) return true
13588
13918
 
13919
+ const image = dom.querySelector("img");
13920
+ if (image && prevNode.altText !== this.altText) {
13921
+ image.alt = this.altText;
13922
+ }
13923
+
13589
13924
  if (prevNode.progress !== this.progress) {
13590
13925
  const progress = dom.querySelector("progress");
13591
13926
  progress.value = this.progress ?? 0;
@@ -13619,7 +13954,7 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
13619
13954
  }
13620
13955
 
13621
13956
  #createDOMForImage() {
13622
- return createElement("img")
13957
+ return createElement("img", { alt: this.altText })
13623
13958
  }
13624
13959
 
13625
13960
  #createDOMForFile() {
@@ -13784,7 +14119,6 @@ class AttachmentNodeConversion {
13784
14119
  const { blob } = this;
13785
14120
  return {
13786
14121
  sgid: blob.attachable_sgid,
13787
- altText: blob.filename,
13788
14122
  contentType: blob.content_type,
13789
14123
  fileName: blob.filename,
13790
14124
  fileSize: blob.byte_size,
@@ -14662,7 +14996,7 @@ class Contents {
14662
14996
  this.#performTextReplacement(anchorNode, lastIndex, stringToReplace, replacementNodes);
14663
14997
  }
14664
14998
 
14665
- uploadFiles(files, { selectLast } = {}) {
14999
+ uploadFiles(files, { selectLast, altText } = {}) {
14666
15000
  if (!this.editorElement) return // Disposed (e.g. on turbo:before-cache); a late drop can still land here
14667
15001
 
14668
15002
  if (!this.editorElement.supportsAttachments) {
@@ -14675,6 +15009,10 @@ class Contents {
14675
15009
  const uploader = Uploader.for(this.editorElement, validFiles);
14676
15010
  uploader.$uploadFiles();
14677
15011
 
15012
+ if (altText && files.length === 1 && uploader.nodes.length === 1) {
15013
+ uploader.nodes[0].getWritable().altText = altText;
15014
+ }
15015
+
14678
15016
  if (selectLast && uploader.nodes?.length) {
14679
15017
  const lastNode = uploader.nodes.at(-1);
14680
15018
  lastNode.selectEnd();
@@ -15459,46 +15797,51 @@ class Clipboard {
15459
15797
  }
15460
15798
 
15461
15799
  #handlePastedFiles(clipboardData) {
15462
- if (!this.editorElement.supportsAttachments) return false
15463
-
15464
- const html = clipboardData.getData("text/html");
15465
- const files = clipboardData.files;
15466
-
15467
- if (files.length && this.#isCopiedImageHTML(html)) {
15468
- this.#uploadFilesPreservingScroll(files);
15469
- return true
15470
- }
15471
-
15472
- if (html && !this.#isLexicalClipboardData(clipboardData)) {
15473
- this.contents.insertHtml(html, { tag: jn });
15474
- return true
15475
- }
15800
+ if (this.editorElement.supportsAttachments) {
15801
+ const html = clipboardData.getData("text/html");
15802
+ const files = clipboardData.files;
15803
+ const copiedImage = files.length && this.#copiedImage(html);
15476
15804
 
15477
- if (files.length) {
15478
- this.#uploadFilesPreservingScroll(files);
15479
- return true
15805
+ if (copiedImage) {
15806
+ this.#uploadFilesPreservingScroll(files, copiedImage.getAttribute("alt"));
15807
+ return true
15808
+ } else if (html && !this.#isLexicalClipboardData(clipboardData)) {
15809
+ this.contents.insertHtml(html, { tag: jn });
15810
+ return true
15811
+ } else if (files.length) {
15812
+ this.#uploadFilesPreservingScroll(files);
15813
+ return true
15814
+ } else {
15815
+ return false
15816
+ }
15817
+ } else {
15818
+ return false
15480
15819
  }
15481
-
15482
- return false
15483
15820
  }
15484
15821
 
15485
15822
  #isLexicalClipboardData(clipboardData) {
15486
15823
  return Array.from(clipboardData.types).includes("application/x-lexical-editor")
15487
15824
  }
15488
15825
 
15489
- #isCopiedImageHTML(html) {
15490
- if (!html) return false
15491
-
15492
- const doc = parseHtml(html);
15493
- const elementChildren = Array.from(doc.body.children);
15826
+ #copiedImage(html) {
15827
+ if (html) {
15828
+ const doc = parseHtml(html);
15829
+ const elementChildren = Array.from(doc.body.children);
15494
15830
 
15495
- return elementChildren.length === 1 && elementChildren[0].tagName === "IMG"
15831
+ if (elementChildren.length === 1 && elementChildren[0].tagName === "IMG") {
15832
+ return elementChildren[0]
15833
+ } else {
15834
+ return null
15835
+ }
15836
+ } else {
15837
+ return null
15838
+ }
15496
15839
  }
15497
15840
 
15498
- #uploadFilesPreservingScroll(files) {
15841
+ #uploadFilesPreservingScroll(files, altText) {
15499
15842
  this.#preservingScrollPosition(() => {
15500
15843
  if (files.length) {
15501
- this.contents.uploadFiles(files, { selectLast: true });
15844
+ this.contents.uploadFiles(files, { selectLast: true, altText });
15502
15845
  }
15503
15846
  });
15504
15847
  }
@@ -16611,6 +16954,318 @@ class AttachmentDragAndDrop {
16611
16954
  }
16612
16955
  }
16613
16956
 
16957
+ // Lexical clears the DOM range on NodeSelection, leaving screen readers in focus
16958
+ // mode to read stray adjacent characters unless we provide a labelled range.
16959
+ class AttachmentFakeSelection {
16960
+ #editor
16961
+ #listeners = new ListenerBin()
16962
+ #container = createElement("span", { className: "lexxy-fake-selection" })
16963
+
16964
+ constructor(editor) {
16965
+ this.#editor = editor;
16966
+ this.#listeners.track(
16967
+ registerLabelledDecoratorSelection(editor, (target) => this.#update(target))
16968
+ );
16969
+ }
16970
+
16971
+ destroy() {
16972
+ this.#listeners.dispose();
16973
+ this.#container.remove();
16974
+ this.#container = null;
16975
+ }
16976
+
16977
+ #update(target) {
16978
+ if (this.#container) {
16979
+ const figure = target && this.#editor.getElementByKey(target.key);
16980
+ if (figure) {
16981
+ const label = target.label || "Attachment";
16982
+ if (this.#container.textContent !== label) this.#container.textContent = label;
16983
+ if (this.#container.parentNode !== figure) figure.append(this.#container);
16984
+ this.#parkSelection();
16985
+ } else {
16986
+ this.#container.remove();
16987
+ }
16988
+ }
16989
+ }
16990
+
16991
+ #parkSelection() {
16992
+ const textNode = this.#container.firstChild;
16993
+ if (textNode && this.#isEditorFocused && !this.#isAlreadyParkedHere) {
16994
+ const range = document.createRange();
16995
+ range.setStart(textNode, 0);
16996
+ range.setEnd(textNode, textNode.length);
16997
+
16998
+ const selection = window.getSelection();
16999
+ selection.removeAllRanges();
17000
+ selection.addRange(range);
17001
+ }
17002
+ }
17003
+
17004
+ // Parking the range while a nested control is focused steals its screen reader cursor.
17005
+ get #isEditorFocused() {
17006
+ const root = this.#editor.getRootElement();
17007
+ return root != null && document.activeElement === root
17008
+ }
17009
+
17010
+ get #isAlreadyParkedHere() {
17011
+ const selection = window.getSelection();
17012
+ if (selection?.rangeCount === 1) {
17013
+ const textNode = this.#container.firstChild;
17014
+ return selection.anchorNode === textNode
17015
+ && selection.focusNode === textNode
17016
+ && selection.anchorOffset === 0
17017
+ && selection.focusOffset === textNode.length
17018
+ } else {
17019
+ return false
17020
+ }
17021
+ }
17022
+ }
17023
+
17024
+ class AttachmentKeyboardMove {
17025
+ #editor
17026
+ #listeners = new ListenerBin()
17027
+ #scrollFrame
17028
+
17029
+ constructor(editor) {
17030
+ this.#editor = editor;
17031
+
17032
+ this.#listeners.track(
17033
+ editor.registerCommand(ve$2, this.#tryReorder, so)
17034
+ );
17035
+ }
17036
+
17037
+ destroy() {
17038
+ this.#listeners.dispose();
17039
+ cancelAnimationFrame(this.#scrollFrame);
17040
+ }
17041
+
17042
+ #tryReorder = (event) => {
17043
+ const node = $singleSelectedNode();
17044
+ if (event.altKey && event.shiftKey && event.key.startsWith("Arrow") && $isActionTextAttachmentNode(node)) {
17045
+ event.preventDefault();
17046
+ const message = this.#executeMove(event.key, node);
17047
+ es($createNodeSelectionWith(node));
17048
+ announceFromEditor(this.#editor, message);
17049
+ this.#keepInView(node);
17050
+ return true
17051
+ } else {
17052
+ return false
17053
+ }
17054
+ }
17055
+
17056
+ #executeMove(key, node) {
17057
+ switch (key) {
17058
+ case "ArrowUp": return new AttachmentReorder(node, "previous").moveVertically()
17059
+ case "ArrowDown": return new AttachmentReorder(node, "next").moveVertically()
17060
+ case "ArrowLeft": return new AttachmentReorder(node, "previous").reorderInGallery()
17061
+ case "ArrowRight": return new AttachmentReorder(node, "next").reorderInGallery()
17062
+ default: return null
17063
+ }
17064
+ }
17065
+
17066
+ // Node selections don't scroll into view automatically like a caret does.
17067
+ #keepInView(node) {
17068
+ const key = node.getKey();
17069
+ cancelAnimationFrame(this.#scrollFrame);
17070
+ this.#scrollFrame = requestAnimationFrame(() => {
17071
+ this.#editor.getElementByKey(key)?.scrollIntoView({ block: "nearest" });
17072
+ });
17073
+ }
17074
+ }
17075
+
17076
+ class AttachmentReorder {
17077
+ constructor(node, direction) {
17078
+ this.node = node;
17079
+ this.direction = direction;
17080
+ }
17081
+
17082
+ moveVertically() {
17083
+ if ($isImageGalleryNode(this.node.getParent())) {
17084
+ return this.#extractFromGallery()
17085
+ } else {
17086
+ return this.#moveBlock() || this.#blockedMessage
17087
+ }
17088
+ }
17089
+
17090
+ reorderInGallery() {
17091
+ const sibling = Ol(this.node, this.direction).getNodeAtCaret();
17092
+ if ($isImageGalleryNode(this.node.getParent()) && sibling) {
17093
+ Ol(sibling, this.direction).insert(this.node);
17094
+ return "Image reordered in gallery"
17095
+ } else {
17096
+ return this.#blockedMessage
17097
+ }
17098
+ }
17099
+
17100
+ #extractFromGallery() {
17101
+ const gallery = this.node.getParent();
17102
+ Ol(gallery, this.direction).insert(this.node);
17103
+ return "Image removed from gallery"
17104
+ }
17105
+
17106
+ #moveBlock() {
17107
+ const target = this.#skipProvisional(Ol(this.node, this.direction).getNodeAtCaret());
17108
+ if (this.#canJoinGallery(target)) {
17109
+ return this.#joinGallery(target)
17110
+ } else if (this.#canFormGalleryWith(target)) {
17111
+ return this.#formGalleryWith(target)
17112
+ } else if (target) {
17113
+ return this.#swapWith(target)
17114
+ } else {
17115
+ return null
17116
+ }
17117
+ }
17118
+
17119
+ #skipProvisional(node) {
17120
+ let current = node;
17121
+ while (current && $isProvisionalParagraphNode(current)) {
17122
+ current = Ol(current, this.direction).getNodeAtCaret();
17123
+ }
17124
+ return current
17125
+ }
17126
+
17127
+ #canJoinGallery(target) {
17128
+ return $isImageGalleryNode(target) && ImageGalleryNode.isValidChild(this.node)
17129
+ }
17130
+
17131
+ #joinGallery(gallery) {
17132
+ Pl(gallery, this.direction).insert(this.node);
17133
+ return "Image added to gallery"
17134
+ }
17135
+
17136
+ #canFormGalleryWith(target) {
17137
+ return $isActionTextAttachmentNode(target)
17138
+ && target.isPreviewableImage
17139
+ && this.node.isPreviewableImage
17140
+ }
17141
+
17142
+ #formGalleryWith(target) {
17143
+ if ($findOrCreateGalleryForImage(target)) {
17144
+ Ol(target, ml(this.direction)).insert(this.node);
17145
+ return "Gallery created"
17146
+ } else {
17147
+ return null
17148
+ }
17149
+ }
17150
+
17151
+ #swapWith(target) {
17152
+ Ol(target, this.direction).insert(this.node);
17153
+ if (this.direction === "next") {
17154
+ return "Attachment moved down"
17155
+ } else {
17156
+ return "Attachment moved up"
17157
+ }
17158
+ }
17159
+
17160
+ get #blockedMessage() {
17161
+ if (this.direction === "next") {
17162
+ return "Already at the end"
17163
+ } else {
17164
+ return "Already at the start"
17165
+ }
17166
+ }
17167
+ }
17168
+
17169
+ // Using a mention's label as avatar alt text can interrupt line-by-line reading,
17170
+ // but character navigation needs it near the caret to announce the mention.
17171
+ class CustomAttachmentLabels {
17172
+ #editor
17173
+ #listeners = new ListenerBin()
17174
+ #active = null
17175
+
17176
+ constructor(editor) {
17177
+ this.#editor = editor;
17178
+ this.#listeners.track(
17179
+ editor.registerUpdateListener(this.#updateLabel),
17180
+ // A blur command opens a Lexical update that can pull focus back into the editor.
17181
+ editor.registerRootListener(rootElement => {
17182
+ if (rootElement) {
17183
+ return registerEventListener(rootElement, "blur", () => this.#restoreLabel())
17184
+ }
17185
+ })
17186
+ );
17187
+ }
17188
+
17189
+ destroy() {
17190
+ this.#listeners.dispose();
17191
+ this.#restoreLabel();
17192
+ }
17193
+
17194
+ #updateLabel = ({ editorState }) => {
17195
+ if (document.activeElement === this.#editor.getRootElement()) {
17196
+ editorState.read(() => {
17197
+ const selection = Qr();
17198
+ const attachment = customAttachmentSelectedBy(selection) || customAttachmentBesideAnchor(selection);
17199
+
17200
+ if (attachment) {
17201
+ this.#exposeLabelOn(attachment);
17202
+ } else {
17203
+ this.#restoreLabel();
17204
+ }
17205
+ });
17206
+ } else {
17207
+ this.#restoreLabel();
17208
+ }
17209
+ }
17210
+
17211
+ #exposeLabelOn(attachment) {
17212
+ const figure = this.#editor.getElementByKey(attachment.getKey());
17213
+ if (figure && figure !== this.#active?.figure) {
17214
+ this.#restoreLabel();
17215
+ attachment.exposeLabel(figure);
17216
+ this.#active = { figure, attachment };
17217
+ }
17218
+ }
17219
+
17220
+ #restoreLabel() {
17221
+ if (this.#active) {
17222
+ const { attachment, figure } = this.#active;
17223
+ attachment.restoreLabel(figure);
17224
+ this.#active = null;
17225
+ }
17226
+ }
17227
+ }
17228
+
17229
+ function customAttachmentSelectedBy(selection) {
17230
+ if (Ir(selection)) {
17231
+ const nodes = selection.getNodes();
17232
+ if (nodes.length === 1 && $isCustomActionTextAttachmentNode(nodes[0])) {
17233
+ return nodes[0]
17234
+ } else {
17235
+ return null
17236
+ }
17237
+ } else {
17238
+ return null
17239
+ }
17240
+ }
17241
+
17242
+ // Screen readers need the label one character early to announce it as the caret
17243
+ // crosses the figure.
17244
+ function customAttachmentBesideAnchor(selection) {
17245
+ if (Fr(selection) && selection.isCollapsed()) {
17246
+ const anchor = selection.anchor;
17247
+ const parent = anchor.getNode();
17248
+ const candidates = [];
17249
+
17250
+ if (anchor.type === "text") {
17251
+ const toEnd = parent.getTextContentSize() - anchor.offset;
17252
+ if (toEnd <= 1) candidates.push({ node: parent.getNextSibling(), distance: toEnd });
17253
+ if (anchor.offset <= 1) candidates.push({ node: parent.getPreviousSibling(), distance: anchor.offset });
17254
+ } else {
17255
+ candidates.push({ node: parent.getChildAtIndex(anchor.offset), distance: 0 });
17256
+ candidates.push({ node: parent.getChildAtIndex(anchor.offset - 1), distance: 0 });
17257
+ }
17258
+
17259
+ const nearest = candidates
17260
+ .filter(({ node }) => $isCustomActionTextAttachmentNode(node))
17261
+ .sort((a, b) => a.distance - b.distance)[0];
17262
+
17263
+ return nearest?.node ?? null
17264
+ } else {
17265
+ return null
17266
+ }
17267
+ }
17268
+
16614
17269
  const ATTACHMENT_ATTRIBUTES = [ "alt", "caption", "content", "content-type", "data-direct-upload-id",
16615
17270
  "data-sgid", "filename", "filesize", "height", "presentation", "previewable", "sgid", "url", "width" ];
16616
17271
 
@@ -16637,12 +17292,19 @@ class AttachmentsExtension extends LexxyExtension {
16637
17292
  ],
16638
17293
  register: (editor) => {
16639
17294
  const dragAndDrop = new AttachmentDragAndDrop(editor);
17295
+ const keyboardMove = new AttachmentKeyboardMove(editor);
17296
+ const fakeSelection = new AttachmentFakeSelection(editor);
17297
+ const customAttachmentLabels = new CustomAttachmentLabels(editor);
16640
17298
 
16641
17299
  return Cc(
16642
17300
  editor.registerNodeTransform(ActionTextAttachmentNode, $extractAttachmentFromParagraph),
16643
17301
  editor.registerCommand(fe$4, $collapseIntoGallery, oo),
17302
+ editor.registerCommand(Fe$2, $focusCaptionFromSelectedAttachment, so),
16644
17303
  editor.registerMutationListener(ActionTextAttachmentUploadNode, this.#handleUploadMutations.bind(this)),
16645
- () => dragAndDrop.destroy()
17304
+ () => dragAndDrop.destroy(),
17305
+ () => keyboardMove.destroy(),
17306
+ () => fakeSelection.destroy(),
17307
+ () => customAttachmentLabels.destroy()
16646
17308
  )
16647
17309
  }
16648
17310
  })
@@ -16740,6 +17402,16 @@ function $collapseAtGalleryEdge(anchor, backwards) {
16740
17402
  }
16741
17403
  }
16742
17404
 
17405
+ function $focusCaptionFromSelectedAttachment(event) {
17406
+ const node = $singleSelectedNode();
17407
+ if (!event.shiftKey && $isActionTextAttachmentNode(node) && node.focusCaption()) {
17408
+ event.preventDefault();
17409
+ return true
17410
+ } else {
17411
+ return false
17412
+ }
17413
+ }
17414
+
16743
17415
  // Manual selection handling to prevent Lexical merging the gallery with a <p> and unwrapping it
16744
17416
  function $moveSelectionBeforeGallery(anchor) {
16745
17417
  const previousNode = anchor.getNode().getPreviousSibling();
@@ -17469,8 +18141,10 @@ class LexicalEditorElement extends HTMLElement {
17469
18141
  #historyState = { undo: false, redo: false }
17470
18142
 
17471
18143
  #validity = new Map()
18144
+ #validationAttempted = false
17472
18145
  #validationTextArea = document.createElement("textarea")
17473
18146
  #uploadRequests
18147
+ #liveRegion
17474
18148
 
17475
18149
  constructor() {
17476
18150
  super();
@@ -17501,6 +18175,10 @@ class LexicalEditorElement extends HTMLElement {
17501
18175
  this.clipboard = new Clipboard(this);
17502
18176
  this.#disposables.push(this.clipboard);
17503
18177
 
18178
+ this.#liveRegion = this.querySelector("lexxy-live-region") ?? createElement("lexxy-live-region");
18179
+ this.append(this.#liveRegion);
18180
+ this.#disposables.push(this.#liveRegion);
18181
+
17504
18182
  this.adapter = new BrowserAdapter();
17505
18183
  this.#uploadRequests = new UploadRequests();
17506
18184
 
@@ -17548,10 +18226,13 @@ class LexicalEditorElement extends HTMLElement {
17548
18226
  }
17549
18227
 
17550
18228
  requiredChangedCallback() {
18229
+ if (this.editorContentElement) this.#synchronizeAriaAttribute("aria-required");
17551
18230
  if (this.isConnected) this.#requestValidityRefresh();
17552
18231
  }
17553
18232
 
17554
18233
  formResetCallback() {
18234
+ this.#validationAttempted = false;
18235
+ this.#synchronizeAriaAttribute("aria-invalid");
17555
18236
  this.value = this.#initialValue;
17556
18237
  this.editor.dispatchCommand(Ye$1, undefined);
17557
18238
  }
@@ -17578,6 +18259,15 @@ class LexicalEditorElement extends HTMLElement {
17578
18259
  return this.internals.validity
17579
18260
  }
17580
18261
 
18262
+ get validationMessage() {
18263
+ return this.internals.validationMessage
18264
+ }
18265
+
18266
+ setCustomValidity(message) {
18267
+ this.#validationTextArea.setCustomValidity(message);
18268
+ this.#refreshValidity();
18269
+ }
18270
+
17581
18271
  checkValidity() {
17582
18272
  return this.internals.checkValidity()
17583
18273
  }
@@ -17646,6 +18336,16 @@ class LexicalEditorElement extends HTMLElement {
17646
18336
  return dispatch(this, "lexxy:file-accept", { file }, true)
17647
18337
  }
17648
18338
 
18339
+ announce(message) {
18340
+ if (message) {
18341
+ if (typeof document.ariaNotify === "function") {
18342
+ document.ariaNotify(message, { priority: "high" });
18343
+ } else {
18344
+ this.#liveRegion?.announce(message);
18345
+ }
18346
+ }
18347
+ }
18348
+
17649
18349
  $generateNodesFromDOM(doc, { editor = this.editor } = {}) {
17650
18350
  let nodes = dt$1(editor, doc);
17651
18351
  if (Es(jn)) nodes = $convertInlineImageDataURIs(nodes, this);
@@ -17805,6 +18505,7 @@ class LexicalEditorElement extends HTMLElement {
17805
18505
  this.#attachDebugHooks();
17806
18506
  this.#attachToolbar();
17807
18507
  this.#resetBeforeTurboCaches();
18508
+ this.#observeAriaAttributes();
17808
18509
 
17809
18510
  this.#setInternalFormValue(this.value, { suppressEvent: true });
17810
18511
  this.#synchronizeWithChanges();
@@ -17877,7 +18578,9 @@ class LexicalEditorElement extends HTMLElement {
17877
18578
  classList: "lexxy-editor__content",
17878
18579
  contenteditable: true,
17879
18580
  role: "textbox",
17880
- "aria-multiline": true,
18581
+ "aria-multiline": this.supportsMultiLine,
18582
+ "aria-required": this.required,
18583
+ "aria-invalid": false,
17881
18584
  "aria-label": this.#labelText,
17882
18585
  placeholder: this.getAttribute("placeholder")
17883
18586
  });
@@ -17910,6 +18613,46 @@ class LexicalEditorElement extends HTMLElement {
17910
18613
  return Array.from(this.attributes).filter(attribute => attribute.name.startsWith("aria-"))
17911
18614
  }
17912
18615
 
18616
+ #observeAriaAttributes() {
18617
+ const observer = new MutationObserver(mutations => {
18618
+ for (const { attributeName } of mutations) {
18619
+ if (attributeName.startsWith("aria-")) {
18620
+ this.#synchronizeAriaAttribute(attributeName);
18621
+ } else if (attributeName === "single-line") {
18622
+ this.#synchronizeAriaAttribute("aria-multiline");
18623
+ }
18624
+ }
18625
+ });
18626
+ observer.observe(this, { attributes: true });
18627
+
18628
+ this.#listeners.track(
18629
+ () => observer.disconnect(),
18630
+ registerEventListener(this, "invalid", () => {
18631
+ this.#validationAttempted = true;
18632
+ this.#synchronizeAriaAttribute("aria-invalid");
18633
+ })
18634
+ );
18635
+ }
18636
+
18637
+ #synchronizeAriaAttribute(name) {
18638
+ const value = this.getAttribute(name) ?? this.#defaultAriaValue(name);
18639
+ if (value === null) {
18640
+ this.editorContentElement.removeAttribute(name);
18641
+ } else if (this.editorContentElement.getAttribute(name) !== String(value)) {
18642
+ this.editorContentElement.setAttribute(name, value);
18643
+ }
18644
+ }
18645
+
18646
+ #defaultAriaValue(name) {
18647
+ switch (name) {
18648
+ case "aria-label": return this.#labelText
18649
+ case "aria-required": return this.required
18650
+ case "aria-multiline": return this.supportsMultiLine
18651
+ case "aria-invalid": return this.#validationAttempted && !this.validity.valid
18652
+ default: return null
18653
+ }
18654
+ }
18655
+
17913
18656
  #setInternalFormValue(html, { suppressEvent = false } = {}) {
17914
18657
  const changed = html !== this.#previousInternalFormValue;
17915
18658
 
@@ -17966,11 +18709,16 @@ class LexicalEditorElement extends HTMLElement {
17966
18709
  #refreshValidity() {
17967
18710
  this.#refreshInternalValidity();
17968
18711
  const { validity, message } = this.#calculateValidity();
17969
- this.internals.setValidity(validity, message, this.editorContentElement);
18712
+ this.internals.setValidity(validity, message, this.editorContentElement ?? undefined);
18713
+ if (this.editorContentElement) {
18714
+ this.#synchronizeAriaAttribute("aria-invalid");
18715
+ }
17970
18716
  }
17971
18717
 
17972
18718
  #refreshInternalValidity() {
17973
- this.#validationTextArea.required = this.required && this.isBlank;
18719
+ if (this.editorContentElement) {
18720
+ this.#validationTextArea.required = this.required && this.isBlank;
18721
+ }
17974
18722
  const flags = this.#validationTextArea.validity;
17975
18723
  const message = this.#validationTextArea.validationMessage;
17976
18724
 
@@ -17985,12 +18733,14 @@ class LexicalEditorElement extends HTMLElement {
17985
18733
  // internal TextArea's ValidityState can contain `valid: true`
17986
18734
  if (flags.valid === true) continue
17987
18735
 
18736
+ let hasError = false;
17988
18737
  for (const flag in flags) {
17989
18738
  if (flags[flag]) {
17990
18739
  validity[flag] = true;
17991
- messages.push(message);
18740
+ hasError = true;
17992
18741
  }
17993
18742
  }
18743
+ if (hasError) messages.push(message);
17994
18744
  }
17995
18745
 
17996
18746
  return { validity, message: messages.join("\n") }
@@ -18011,6 +18761,9 @@ class LexicalEditorElement extends HTMLElement {
18011
18761
  );
18012
18762
  this.#registerTableComponents();
18013
18763
  this.#registerCodeLanguagePicker();
18764
+ if (this.supportsAttachments) {
18765
+ this.#registerAttachmentToolbar();
18766
+ }
18014
18767
  if (this.supportsMarkdown) {
18015
18768
  const transformers = [ ...te, HORIZONTAL_DIVIDER ];
18016
18769
  registered.push(
@@ -18039,6 +18792,15 @@ class LexicalEditorElement extends HTMLElement {
18039
18792
  this.#disposables.push(codeLanguagePicker);
18040
18793
  }
18041
18794
 
18795
+ #registerAttachmentToolbar() {
18796
+ let attachmentToolbar = this.querySelector("lexxy-attachment-toolbar");
18797
+ attachmentToolbar ??= createElement("lexxy-attachment-toolbar");
18798
+ this.append(attachmentToolbar);
18799
+ this.#disposables.push(attachmentToolbar);
18800
+ this.captionEditor = new CaptionEditor(this);
18801
+ this.#disposables.push(this.captionEditor);
18802
+ }
18803
+
18042
18804
  #handleEnter() {
18043
18805
  // We can't prevent these externally using regular keydown because Lexical handles it first.
18044
18806
  this.#listeners.track(this.editor.registerCommand(
@@ -18247,21 +19009,22 @@ class LexicalEditorElement extends HTMLElement {
18247
19009
  // — triggering at most one forced reflow. The previous implementation interleaved
18248
19010
  // setProperty/getComputedStyle/removeProperty on the same element, forcing a style
18249
19011
  // recalc on every iteration during editor initialization.
18250
- #resolveColors(property, cssValues) {
19012
+ #resolveColors(property, buttons) {
18251
19013
  const container = document.createElement("span");
18252
19014
  container.style.display = "none";
18253
19015
 
18254
- const resolvers = cssValues.map(cssValue => {
19016
+ const resolvers = normalizeColorButtons(buttons).map(({ value, label }) => {
18255
19017
  const element = document.createElement("span");
18256
- element.style.setProperty(property, cssValue);
19018
+ element.style.setProperty(property, value);
18257
19019
  container.appendChild(element);
18258
- return { element, name: cssValue }
19020
+ return { element, name: value, label }
18259
19021
  });
18260
19022
 
18261
19023
  styleResolverRoot().appendChild(container);
18262
19024
 
18263
- const resolved = resolvers.map(({ element, name }) => ({
19025
+ const resolved = resolvers.map(({ element, name, label }) => ({
18264
19026
  name,
19027
+ label,
18265
19028
  value: window.getComputedStyle(element).getPropertyValue(property)
18266
19029
  }));
18267
19030
 
@@ -18295,6 +19058,7 @@ class LexicalEditorElement extends HTMLElement {
18295
19058
 
18296
19059
  #resetValidity() {
18297
19060
  this.#validity = new Map();
19061
+ this.#validationAttempted = false;
18298
19062
  }
18299
19063
  }
18300
19064
 
@@ -18325,6 +19089,39 @@ function $getReadableTextContent(node) {
18325
19089
  return node.getTextContent()
18326
19090
  }
18327
19091
 
19092
+ const REMOVAL_DELAY = 1000;
19093
+
19094
+ class LiveRegion extends HTMLElement {
19095
+ #additions = createElement("span", { ariaLive: "assertive", ariaRelevant: "additions" })
19096
+ #removalTimeouts = new Set()
19097
+
19098
+ connectedCallback() {
19099
+ this.replaceChildren(this.#additions);
19100
+ }
19101
+
19102
+ disconnectedCallback() {
19103
+ this.dispose();
19104
+ }
19105
+
19106
+ dispose() {
19107
+ for (const timeout of this.#removalTimeouts) clearTimeout(timeout);
19108
+ this.#removalTimeouts.clear();
19109
+ this.#additions.replaceChildren();
19110
+ this.replaceChildren();
19111
+ }
19112
+
19113
+ announce(message) {
19114
+ const announcement = createElement("div", { textContent: message });
19115
+ this.#additions.appendChild(announcement);
19116
+
19117
+ const timeout = setTimeout(() => {
19118
+ announcement.remove();
19119
+ this.#removalTimeouts.delete(timeout);
19120
+ }, REMOVAL_DELAY);
19121
+ this.#removalTimeouts.add(timeout);
19122
+ }
19123
+ }
19124
+
18328
19125
  class BaseSource {
18329
19126
  // Template method to override
18330
19127
  async buildListItems(filter = "") {
@@ -19207,50 +20004,373 @@ class CodeLanguagePicker extends HTMLElement {
19207
20004
  }
19208
20005
  }
19209
20006
 
20007
+ class AlternativeTextDialog {
20008
+ #editor
20009
+ #editorElement
20010
+ #dialog
20011
+ #input
20012
+ #nodeKey
20013
+ #elementToRefocus
20014
+ #listeners = new ListenerBin()
20015
+
20016
+ constructor(editorElement) {
20017
+ this.#editor = editorElement.editor;
20018
+ this.#editorElement = editorElement;
20019
+ this.#dialog = createElement("dialog", { className: "lexxy-alternative-text-dialog", ariaLabel: "Alternative text" });
20020
+ this.#input = createElement("textarea", { rows: 1, autofocus: true, ariaLabel: "Description", placeholder: "Keep it short, but enough to convey the context…" });
20021
+
20022
+ const title = createElement("h2", { textContent: "Describe the image for people who can't see it:" });
20023
+
20024
+ const actions = createElement("div", { className: "lexxy-alternative-text-dialog__actions" });
20025
+ const cancel = createElement("button", { type: "button", textContent: "Cancel" });
20026
+ const save = createElement("button", { type: "button", className: "lexxy-alternative-text-dialog__save", textContent: "Save" });
20027
+ actions.append(cancel, save);
20028
+
20029
+ const controls = createElement("div", { className: "lexxy-alternative-text-dialog__controls" });
20030
+ controls.append(this.#input, actions);
20031
+ this.#dialog.append(title, controls);
20032
+ editorElement.appendChild(this.#dialog);
20033
+
20034
+ this.#listeners.track(
20035
+ registerEventListener(cancel, "click", () => this.#close()),
20036
+ registerEventListener(save, "click", () => this.#save()),
20037
+ registerEventListener(this.#dialog, "keydown", this.#handleKeyDown),
20038
+ registerEventListener(document, "pointerdown", this.#closeOnClickOutside)
20039
+ );
20040
+ }
20041
+
20042
+ dispose() {
20043
+ this.#dialog.remove();
20044
+ this.#listeners.dispose();
20045
+ }
20046
+
20047
+ open(nodeKey) {
20048
+ const description = this.#editor.read(() => {
20049
+ const node = Yo(nodeKey);
20050
+ if ($isActionTextAttachmentNode(node)) {
20051
+ return node.altText
20052
+ }
20053
+ });
20054
+
20055
+ if (description !== undefined) {
20056
+ this.#nodeKey = nodeKey;
20057
+ this.#input.value = description;
20058
+ this.#anchorBelowAttachment(nodeKey);
20059
+ this.#elementToRefocus = document.activeElement;
20060
+ this.#editorElement.querySelector("lexxy-toolbar")?.closeDropdowns();
20061
+ this.#dialog.show();
20062
+ this.#input.focus();
20063
+ }
20064
+ }
20065
+
20066
+ #anchorBelowAttachment(nodeKey) {
20067
+ const figureElement = this.#editor.getElementByKey(nodeKey);
20068
+ if (figureElement) {
20069
+ const rect = figureElement.getBoundingClientRect();
20070
+ const editorRect = this.#editorElement.getBoundingClientRect();
20071
+ const bottom = rect.bottom - editorRect.top - this.#editorElement.clientTop + this.#editorElement.scrollTop;
20072
+ this.#dialog.style.setProperty("--lexxy-anchor-bottom", `${bottom}px`);
20073
+ }
20074
+ }
20075
+
20076
+ #save() {
20077
+ const description = this.#input.value.trim();
20078
+ this.#editor.update(() => {
20079
+ const node = Yo(this.#nodeKey);
20080
+ if ($isActionTextAttachmentNode(node) && node.altText !== description) {
20081
+ node.getWritable().altText = description;
20082
+ }
20083
+ }, { tag: [ $n$1, qn ] });
20084
+ this.#close();
20085
+ }
20086
+
20087
+ #handleKeyDown = (event) => {
20088
+ event.stopPropagation();
20089
+ if (event.key === "Escape") {
20090
+ this.#close();
20091
+ } else {
20092
+ trapFocusAtTabBoundary(this.#dialog, event);
20093
+ }
20094
+ }
20095
+
20096
+ // Dismissing by clicking elsewhere must leave focus where the click landed.
20097
+ #closeOnClickOutside = (event) => {
20098
+ if (this.#dialog.open && !this.#dialog.contains(event.target)) {
20099
+ this.#close({ refocus: false });
20100
+ }
20101
+ }
20102
+
20103
+ #close({ refocus = true } = {}) {
20104
+ this.#dialog.close();
20105
+ if (refocus && this.#elementToRefocus?.isConnected) {
20106
+ this.#elementToRefocus.focus();
20107
+ }
20108
+ this.#elementToRefocus = null;
20109
+ }
20110
+ }
20111
+
19210
20112
  const DELETE_ICON = `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
19211
20113
  <path d="M11.2041 1.01074C12.2128 1.113 13 1.96435 13 3V4H15L15.1025 4.00488C15.6067 4.05621 16 4.48232 16 5C16 5.55228 15.5523 6 15 6H14.8457L14.1416 15.1533C14.0614 16.1953 13.1925 17 12.1475 17H5.85254L5.6582 16.9902C4.76514 16.9041 4.03607 16.2296 3.88184 15.3457L3.8584 15.1533L3.1543 6H3C2.44772 6 2 5.55228 2 5C2 4.44772 2.44772 4 3 4H5V3C5 1.89543 5.89543 1 7 1H11L11.2041 1.01074ZM5.85254 15H12.1475L12.8398 6H5.16016L5.85254 15ZM7 4H11V3H7V4Z"/>
19212
20114
  </svg>`;
19213
20115
 
19214
- class NodeDeleteButton extends HTMLElement {
20116
+ class AttachmentToolbar extends HTMLElement {
20117
+ #listeners = new ListenerBin()
20118
+ #buttons = []
20119
+ #alternativeTextButton
20120
+ #alternativeTextDialog
20121
+ #currentNodeKey = null
20122
+ #reflowObserver = new ResizeObserver(() => this.#updatePosition())
20123
+ #presentationObserver = new MutationObserver(() => this.#refresh())
20124
+ #observedElement = null
20125
+
19215
20126
  connectedCallback() {
19216
- this.editorElement = this.closest("lexxy-editor");
19217
- this.editor = this.editorElement.editor;
19218
20127
  this.classList.add("lexxy-floating-controls");
20128
+ this.role = "toolbar";
20129
+ this.hidden = true;
19219
20130
 
19220
- if (!this.querySelector(".lexxy-node-delete")) {
19221
- this.#attachDeleteButton();
20131
+ if (this.#editor) {
20132
+ this.#setUpButtons();
20133
+ this.#monitorSelection();
20134
+ this.#followScrolling();
20135
+ this.#registerKeyboardShortcut();
19222
20136
  }
19223
20137
  }
19224
20138
 
19225
20139
  disconnectedCallback() {
19226
- this.editor = null;
19227
- this.editorElement = null;
20140
+ this.dispose();
20141
+ }
20142
+
20143
+ dispose() {
20144
+ this.#listeners.dispose();
20145
+ this.#reflowObserver.disconnect();
20146
+ this.#presentationObserver.disconnect();
20147
+ this.#alternativeTextDialog?.dispose();
20148
+ }
20149
+
20150
+ get #editor() {
20151
+ return this.#editorElement?.editor
20152
+ }
20153
+
20154
+ get #editorElement() {
20155
+ return this.closest("lexxy-editor")
19228
20156
  }
19229
20157
 
19230
- #attachDeleteButton() {
20158
+ #setUpButtons() {
20159
+ this.innerHTML = "";
20160
+
19231
20161
  const container = createElement("div", { className: "lexxy-floating-controls__group" });
20162
+ container.appendChild(this.#createAlternativeTextButton());
20163
+ container.appendChild(this.#createRemoveButton());
20164
+ this.#alternativeTextDialog = new AlternativeTextDialog(this.#editorElement);
20165
+ this.appendChild(container);
20166
+
20167
+ this.#buttons = Array.from(this.querySelectorAll("button"));
20168
+ this.#listeners.track(
20169
+ registerEventListener(this, "keydown", this.#navigateOrExit),
20170
+ registerEventListener(this, "focusout", this.#resetTabIndexOnExit)
20171
+ );
20172
+ }
19232
20173
 
19233
- this.deleteButton = createElement("button", {
19234
- className: "lexxy-node-delete",
20174
+ #createRemoveButton() {
20175
+ const button = createElement("button", {
19235
20176
  type: "button",
19236
- "aria-label": "Remove"
20177
+ className: "lexxy-attachment-toolbar__remove",
20178
+ ariaLabel: "Remove",
20179
+ tabIndex: -1
19237
20180
  });
19238
- this.deleteButton.tabIndex = -1;
19239
- this.deleteButton.innerHTML = DELETE_ICON;
20181
+ button.innerHTML = DELETE_ICON;
20182
+ this.#listeners.track(registerEventListener(button, "click", () => this.#removeSelectedNode()));
20183
+ return button
20184
+ }
19240
20185
 
19241
- this.handleDeleteClick = () => this.#deleteNode();
19242
- this.deleteButton.addEventListener("click", this.handleDeleteClick);
19243
- container.appendChild(this.deleteButton);
20186
+ #removeSelectedNode() {
20187
+ if (this.#hasSelectedNode) {
20188
+ this.#editor.update(() => Yo(this.#currentNodeKey)?.remove());
20189
+ this.#editor.focus();
20190
+ }
20191
+ }
19244
20192
 
19245
- this.appendChild(container);
20193
+ get #hasSelectedNode() {
20194
+ return this.#currentNodeKey !== null
19246
20195
  }
19247
20196
 
19248
- #deleteNode() {
19249
- this.editor.update(() => {
19250
- const node = Go(this);
19251
- node?.remove();
20197
+ #createAlternativeTextButton() {
20198
+ this.#alternativeTextButton = createElement("button", {
20199
+ type: "button",
20200
+ className: "lexxy-attachment-toolbar__alternative-text",
20201
+ ariaLabel: "Alternative text",
20202
+ title: "Alternative text",
20203
+ ariaHasPopup: "dialog",
20204
+ tabIndex: -1
20205
+ });
20206
+ this.#alternativeTextButton.appendChild(createElement("span", null, "ALT"));
20207
+ this.#listeners.track(registerEventListener(this.#alternativeTextButton, "click", () => {
20208
+ this.#alternativeTextDialog.open(this.#currentNodeKey);
20209
+ }));
20210
+ return this.#alternativeTextButton
20211
+ }
20212
+
20213
+ #navigateOrExit = (event) => {
20214
+ if (event.key === "Escape") {
20215
+ event.preventDefault();
20216
+ event.stopPropagation();
20217
+ this.#returnFocusToEditor();
20218
+ } else {
20219
+ handleRollingTabIndex(this.#buttons, event);
20220
+ }
20221
+ }
20222
+
20223
+ #returnFocusToEditor() {
20224
+ this.#editor.getRootElement()?.focus({ preventScroll: true });
20225
+ if (this.#currentNodeKey) {
20226
+ const nodeKey = this.#currentNodeKey;
20227
+ this.#editor.update(() => {
20228
+ const node = Yo(nodeKey);
20229
+ if (node) es($createNodeSelectionWith(node));
20230
+ });
20231
+ }
20232
+ }
20233
+
20234
+ #resetTabIndexOnExit = (event) => {
20235
+ if (!this.contains(event.relatedTarget)) {
20236
+ this.#buttons.forEach(button => button.tabIndex = -1);
20237
+ }
20238
+ }
20239
+
20240
+ #monitorSelection() {
20241
+ this.#listeners.track(
20242
+ registerLabelledDecoratorSelection(this.#editor, (target) => this.#updateForSelection(target))
20243
+ );
20244
+ }
20245
+
20246
+ #updateForSelection(target) {
20247
+ if (target) {
20248
+ this.#show(target.key);
20249
+ } else {
20250
+ this.#hide();
20251
+ }
20252
+ }
20253
+
20254
+ #show(nodeKey) {
20255
+ this.#currentNodeKey = nodeKey;
20256
+ this.#refresh();
20257
+ this.hidden = false;
20258
+ this.#reflowObserver.observe(this.#editorElement);
20259
+ }
20260
+
20261
+ #refresh() {
20262
+ if (this.#hasSelectedNode) {
20263
+ this.#watchPresentation(this.#currentNodeKey);
20264
+ this.#describeNode(this.#currentNodeKey);
20265
+ this.#updatePosition();
20266
+ }
20267
+ }
20268
+
20269
+ // Failed previews change presentation without a Lexical update, and a node
20270
+ // can replace its figure without changing its key.
20271
+ #watchPresentation(nodeKey) {
20272
+ const element = this.#editor.getElementByKey(nodeKey);
20273
+ if (element !== this.#observedElement) {
20274
+ this.#presentationObserver.disconnect();
20275
+ this.#observedElement = element;
20276
+ if (element) this.#presentationObserver.observe(element, { attributes: true, attributeFilter: [ "class" ] });
20277
+ }
20278
+ }
20279
+
20280
+ #describeNode(nodeKey) {
20281
+ const element = this.#editor.getElementByKey(nodeKey);
20282
+
20283
+ this.#editor.getEditorState().read(() => {
20284
+ const node = Yo(nodeKey);
20285
+ this.#alternativeTextButton.hidden = !this.#canEditAlternativeText(node);
20286
+ this.dataset.nodeType = node.getType();
20287
+ this.dataset.presentation = this.#presentationOf(node, element);
20288
+
20289
+ if (node.contentType) {
20290
+ this.dataset.contentType = node.contentType;
20291
+ } else {
20292
+ delete this.dataset.contentType;
20293
+ }
19252
20294
  });
19253
20295
  }
20296
+
20297
+ #canEditAlternativeText(node) {
20298
+ return this.#editorElement.dataset.actionTextSupportsAlt !== "false"
20299
+ && node.getType() === "action_text_attachment"
20300
+ && node.isPreviewableAttachment
20301
+ }
20302
+
20303
+ #presentationOf(node, element) {
20304
+ if ($isImageGalleryNode(node.getParent())) {
20305
+ return "gallery"
20306
+ } else if (node.isInline() && this.#rendersInline(element)) {
20307
+ return "inline"
20308
+ } else if (element?.classList.contains("attachment--preview")) {
20309
+ return "preview"
20310
+ } else {
20311
+ return "block"
20312
+ }
20313
+ }
20314
+
20315
+ #rendersInline(element) {
20316
+ return element != null && getComputedStyle(element).display.startsWith("inline")
20317
+ }
20318
+
20319
+ #updatePosition() {
20320
+ const figureElement = this.#editor.getElementByKey(this.#currentNodeKey);
20321
+ if (figureElement) {
20322
+ const rect = figureElement.getBoundingClientRect();
20323
+ const editorRect = this.#editorElement.getBoundingClientRect();
20324
+ // We are positioned against the editor's padding box, but the rect measures its border box.
20325
+ const borderTop = this.#editorElement.clientTop;
20326
+ const borderLeft = this.#editorElement.clientLeft;
20327
+ this.style.setProperty("--lexxy-anchor-top", `${rect.top - editorRect.top - borderTop}px`);
20328
+ this.style.setProperty("--lexxy-anchor-left", `${rect.left - editorRect.left - borderLeft}px`);
20329
+ this.style.setProperty("--lexxy-anchor-width", `${rect.width}px`);
20330
+ this.style.setProperty("--lexxy-anchor-height", `${rect.height}px`);
20331
+ this.#flipWhenOverflowing(editorRect);
20332
+ }
20333
+ }
20334
+
20335
+ #flipWhenOverflowing(editorRect) {
20336
+ this.removeAttribute("data-overflow");
20337
+ if (this.getBoundingClientRect().right > editorRect.right) {
20338
+ this.setAttribute("data-overflow", "");
20339
+ }
20340
+ }
20341
+
20342
+ #hide() {
20343
+ if (this.#hasSelectedNode) {
20344
+ this.#currentNodeKey = null;
20345
+ this.hidden = true;
20346
+ this.#reflowObserver.disconnect();
20347
+ this.#presentationObserver.disconnect();
20348
+ this.#observedElement = null;
20349
+ }
20350
+ }
20351
+
20352
+ // Scrolling inside the editor moves the figure without resizing anything.
20353
+ #followScrolling() {
20354
+ this.#listeners.track(registerEventListener(this.#editorElement, "scroll", () => this.#updatePosition(), { capture: true, passive: true }));
20355
+ }
20356
+
20357
+ #registerKeyboardShortcut() {
20358
+ this.#listeners.track(this.#editor.registerCommand(
20359
+ ve$2,
20360
+ this.#focusToolbarOnAltF10,
20361
+ so
20362
+ ));
20363
+ }
20364
+
20365
+ #focusToolbarOnAltF10 = (event) => {
20366
+ if (this.#hasSelectedNode && event.altKey && event.key === "F10") {
20367
+ event.preventDefault();
20368
+ this.#buttons.find(isActiveAndVisible)?.focus();
20369
+ return true
20370
+ } else {
20371
+ return false
20372
+ }
20373
+ }
19254
20374
  }
19255
20375
 
19256
20376
  class TableController {
@@ -19655,7 +20775,7 @@ class TableTools extends HTMLElement {
19655
20775
  #listeners = new ListenerBin()
19656
20776
 
19657
20777
  connectedCallback() {
19658
- this.tableController = new TableController(this.#editorElement);
20778
+ this.tableController = new TableController(this.editorElement);
19659
20779
  this.classList.add("lexxy-floating-controls");
19660
20780
  this.role = "toolbar";
19661
20781
 
@@ -19676,16 +20796,34 @@ class TableTools extends HTMLElement {
19676
20796
  this.tableController = null;
19677
20797
  }
19678
20798
 
19679
- get #editor() {
19680
- return this.#editorElement.editor
20799
+ get editorElement() {
20800
+ return this.closest("lexxy-editor")
19681
20801
  }
19682
20802
 
19683
- get #editorElement() {
19684
- return this.closest("lexxy-editor")
20803
+ get editor() {
20804
+ return this.editorElement.editor
20805
+ }
20806
+
20807
+ getEditorElement() {
20808
+ return this.editorElement
20809
+ }
20810
+
20811
+ closeDropdowns({ except } = {}) {
20812
+ this.#moreMenus.forEach(menu => {
20813
+ if (menu !== except) menu.close({ focusEditor: false });
20814
+ });
20815
+ }
20816
+
20817
+ get #moreMenus() {
20818
+ return this.querySelectorAll("lexxy-toolbar-dropdown")
20819
+ }
20820
+
20821
+ get #hasOpenMoreMenu() {
20822
+ return Array.from(this.#moreMenus).some(menu => menu.isOpen)
19685
20823
  }
19686
20824
 
19687
20825
  get #tableToolsButtons() {
19688
- return Array.from(this.querySelectorAll("button, details > summary"))
20826
+ return Array.from(this.querySelectorAll("button")).filter(button => !button.closest("[data-dropdown-panel]"))
19689
20827
  }
19690
20828
 
19691
20829
  #setUpButtons() {
@@ -19704,23 +20842,37 @@ class TableTools extends HTMLElement {
19704
20842
  const plusButton = this.#createButton(`Add ${childType}`, { action: "insert", childType, direction: "after" }, "+");
19705
20843
  const minusButton = this.#createButton(`Remove ${childType}`, { action: "delete", childType }, "−");
19706
20844
 
19707
- const dropdown = createElement("details", { className: "lexxy-table-control__more-menu" });
19708
- dropdown.setAttribute("name", "lexxy-dropdown");
19709
- dropdown.tabIndex = -1;
19710
-
19711
- const count = createElement("summary", {}, `_ ${childType}s`);
19712
- setCountProperty(count);
19713
- dropdown.appendChild(count);
19714
-
19715
- dropdown.appendChild(moreMenu);
19716
-
19717
20845
  container.appendChild(minusButton);
19718
- container.appendChild(dropdown);
20846
+ container.appendChild(this.#createMoreMenu(childType, setCountProperty, moreMenu));
19719
20847
  container.appendChild(plusButton);
19720
20848
 
19721
20849
  return container
19722
20850
  }
19723
20851
 
20852
+ #createMoreMenu(childType, setCountProperty, menu) {
20853
+ const dropdown = createElement("lexxy-toolbar-dropdown", { className: "lexxy-table-control__more-menu" });
20854
+
20855
+ const trigger = createElement("button", {
20856
+ type: "button",
20857
+ className: "lexxy-table-control__more-menu-trigger",
20858
+ dataset: { dropdownTrigger: "" },
20859
+ "aria-haspopup": "menu",
20860
+ "aria-expanded": "false"
20861
+ }, `_ ${childType}s`);
20862
+ trigger.tabIndex = -1;
20863
+ setCountProperty(trigger);
20864
+
20865
+ menu.dataset.dropdownPanel = "";
20866
+ menu.role = "menu";
20867
+ menu.setAttribute("aria-label", `${childType} options`);
20868
+ menu.hidden = true;
20869
+
20870
+ dropdown.appendChild(trigger);
20871
+ dropdown.appendChild(menu);
20872
+
20873
+ return dropdown
20874
+ }
20875
+
19724
20876
  #createRowButtonsContainer() {
19725
20877
  return this.#createButtonsContainer(
19726
20878
  "row",
@@ -19739,15 +20891,18 @@ class TableTools extends HTMLElement {
19739
20891
 
19740
20892
  #createMoreMenuSection(childType) {
19741
20893
  const section = createElement("div", { className: "lexxy-floating-controls__group lexxy-table-control__more-menu-details" });
19742
- const addBeforeButton = this.#createButton(`Add ${childType} before`, { action: "insert", childType, direction: "before" });
19743
- const addAfterButton = this.#createButton(`Add ${childType} after`, { action: "insert", childType, direction: "after" });
19744
- const toggleStyleButton = this.#createButton(`Toggle ${childType} style`, { action: "toggle", childType });
19745
- const deleteButton = this.#createButton(`Remove ${childType}`, { action: "delete", childType });
19746
20894
 
19747
- section.appendChild(addBeforeButton);
19748
- section.appendChild(addAfterButton);
19749
- section.appendChild(toggleStyleButton);
19750
- section.appendChild(deleteButton);
20895
+ const items = [
20896
+ this.#createButton(`Add ${childType} before`, { action: "insert", childType, direction: "before" }),
20897
+ this.#createButton(`Add ${childType} after`, { action: "insert", childType, direction: "after" }),
20898
+ this.#createButton(`Toggle ${childType} style`, { action: "toggle", childType }),
20899
+ this.#createButton(`Remove ${childType}`, { action: "delete", childType })
20900
+ ];
20901
+
20902
+ items.forEach(item => {
20903
+ item.role = "menuitem";
20904
+ section.appendChild(item);
20905
+ });
19751
20906
 
19752
20907
  return section
19753
20908
  }
@@ -19788,7 +20943,7 @@ class TableTools extends HTMLElement {
19788
20943
  }
19789
20944
 
19790
20945
  #registerKeyboardShortcuts() {
19791
- this.#listeners.track(this.#editor.registerCommand(ve$2, this.#focusToolbarOnAltF10, so));
20946
+ this.#listeners.track(this.editor.registerCommand(ve$2, this.#focusToolbarOnAltF10, so));
19792
20947
  }
19793
20948
 
19794
20949
  #focusToolbarOnAltF10 = (event) => {
@@ -19819,9 +20974,9 @@ class TableTools extends HTMLElement {
19819
20974
  const cell = this.tableController.currentCell;
19820
20975
  if (!cell) return
19821
20976
 
19822
- this.#editor.update(() => {
20977
+ this.editor.update(() => {
19823
20978
  cell.select();
19824
- this.#editor.focus();
20979
+ this.editor.focus();
19825
20980
  });
19826
20981
 
19827
20982
  this.#update();
@@ -19858,7 +21013,7 @@ class TableTools extends HTMLElement {
19858
21013
  if (!cellsToHighlight) return
19859
21014
 
19860
21015
  cellsToHighlight.forEach(cell => {
19861
- const cellElement = this.#editor.getElementByKey(cell.getKey());
21016
+ const cellElement = this.editor.getElementByKey(cell.getKey());
19862
21017
  if (!cellElement) return
19863
21018
 
19864
21019
  cellElement.classList.toggle(theme.tableCellHighlight, true);
@@ -19867,8 +21022,8 @@ class TableTools extends HTMLElement {
19867
21022
  }
19868
21023
 
19869
21024
  #monitorForTableSelection() {
19870
- this.#listeners.track(this.#editor.registerUpdateListener(() => {
19871
- const tableNode = this.#editor.getRootElement() && this.tableController.updateSelectedTable();
21025
+ this.#listeners.track(this.editor.registerUpdateListener(() => {
21026
+ const tableNode = this.editor.getRootElement() && this.tableController.updateSelectedTable();
19872
21027
 
19873
21028
  if (tableNode) {
19874
21029
  this.#show();
@@ -19879,8 +21034,12 @@ class TableTools extends HTMLElement {
19879
21034
  }
19880
21035
 
19881
21036
  #executeTableCommand(command) {
21037
+ const fromMoreMenu = this.#hasOpenMoreMenu;
21038
+
19882
21039
  this.tableController.executeTableCommand(command);
19883
21040
  this.#update();
21041
+
21042
+ if (fromMoreMenu) this.editor.focus();
19884
21043
  }
19885
21044
 
19886
21045
  #show() {
@@ -19904,18 +21063,18 @@ class TableTools extends HTMLElement {
19904
21063
  }
19905
21064
 
19906
21065
  #closeMoreMenu() {
19907
- this.querySelector("details[open]")?.removeAttribute("open");
21066
+ this.closeDropdowns();
19908
21067
  }
19909
21068
 
19910
21069
  #updateButtonsPosition() {
19911
21070
  const tableNode = this.tableController.currentTableNode;
19912
21071
  if (!tableNode) return
19913
21072
 
19914
- const tableElement = this.#editor.getElementByKey(tableNode.getKey());
21073
+ const tableElement = this.editor.getElementByKey(tableNode.getKey());
19915
21074
  if (!tableElement) return
19916
21075
 
19917
21076
  const tableRect = tableElement.getBoundingClientRect();
19918
- const editorRect = this.#editorElement.getBoundingClientRect();
21077
+ const editorRect = this.editorElement.getBoundingClientRect();
19919
21078
 
19920
21079
  const relativeTop = tableRect.top - editorRect.top;
19921
21080
  const relativeCenter = (tableRect.left + tableRect.right) / 2 - editorRect.left;
@@ -19927,7 +21086,7 @@ class TableTools extends HTMLElement {
19927
21086
  const tableNode = this.tableController.currentTableNode;
19928
21087
  if (!tableNode) return
19929
21088
 
19930
- const tableElement = xn(this.#editor, tableNode);
21089
+ const tableElement = xn(this.editor, tableNode);
19931
21090
  if (!tableElement) return
19932
21091
 
19933
21092
  const rowCount = tableElement.rows;
@@ -19941,18 +21100,18 @@ class TableTools extends HTMLElement {
19941
21100
  const cell = this.tableController.currentCell;
19942
21101
  if (!cell) return
19943
21102
 
19944
- const cellElement = this.#editor.getElementByKey(cell.getKey());
19945
- if (!cellElement) return
21103
+ const cellElement = this.editor.getElementByKey(cell.getKey());
21104
+ if (!cellElement?.contains(document.getSelection()?.anchorNode)) return
19946
21105
 
19947
21106
  cellElement.classList.add(theme.tableCellFocus);
19948
21107
  }
19949
21108
 
19950
21109
  #clearCellStyles() {
19951
- this.#editorElement.querySelectorAll(`.${theme.tableCellFocus}`)?.forEach(cell => {
21110
+ this.editorElement.querySelectorAll(`.${theme.tableCellFocus}`)?.forEach(cell => {
19952
21111
  cell.classList.remove(theme.tableCellFocus);
19953
21112
  });
19954
21113
 
19955
- this.#editorElement.querySelectorAll(`.${theme.tableCellHighlight}`)?.forEach(cell => {
21114
+ this.editorElement.querySelectorAll(`.${theme.tableCellHighlight}`)?.forEach(cell => {
19956
21115
  cell.classList.remove(theme.tableCellHighlight);
19957
21116
  cell.removeAttribute("data-action");
19958
21117
  cell.removeAttribute("data-child-type");
@@ -19984,7 +21143,8 @@ function defineElements() {
19984
21143
  // Prompt must be registered AFTER Editor
19985
21144
  "lexxy-prompt": LexicalPromptElement,
19986
21145
  "lexxy-code-language-picker": CodeLanguagePicker,
19987
- "lexxy-node-delete-button": NodeDeleteButton,
21146
+ "lexxy-live-region": LiveRegion,
21147
+ "lexxy-attachment-toolbar": AttachmentToolbar,
19988
21148
  "lexxy-table-tools": TableTools
19989
21149
  };
19990
21150