inclusive-elements 0.6.1 → 0.7.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -30,7 +30,8 @@ function i(e, t) {
30
30
  let n = e.style;
31
31
  for (let e of Object.keys(t)) n[e] = t[e] ?? "";
32
32
  }
33
- var a = /* @__PURE__ */ new WeakMap(), o = [
33
+ var a = /* @__PURE__ */ new WeakMap();
34
+ var o = [
34
35
  "margin",
35
36
  "marginTop",
36
37
  "marginRight",
@@ -42,7 +43,8 @@ var a = /* @__PURE__ */ new WeakMap(), o = [
42
43
  "marginInline",
43
44
  "marginInlineStart",
44
45
  "marginInlineEnd"
45
- ], s = {};
46
+ ];
47
+ var s = {};
46
48
  for (let e of o) s[e] = "0px";
47
49
  async function c(r, i, o = {}) {
48
50
  let s = e(o) + i + "-", c = Symbol(s), u = o.detachFromLayout ?? !1, f = u ? g(r) : void 0, p = u ? d(r, f) : void 0, m = i === "leave" ? _(r) : void 0, h = {
@@ -137,7 +139,9 @@ function _(e) {
137
139
  e.inert = t;
138
140
  };
139
141
  }
140
- var v = /* @__PURE__ */ new WeakMap(), y = /* @__PURE__ */ new WeakMap(), b = /* @__PURE__ */ new WeakMap();
142
+ var v = /* @__PURE__ */ new WeakMap();
143
+ var y = /* @__PURE__ */ new WeakMap();
144
+ var b = /* @__PURE__ */ new WeakMap();
141
145
  function x(t, n, r = {}) {
142
146
  let i = [];
143
147
  for (let e of Array.from(t)) getComputedStyle(e).display !== "none" && i.push({
@@ -148,20 +152,20 @@ function x(t, n, r = {}) {
148
152
  let a = e(r) + "move", o = [];
149
153
  for (let { el: e, before: t } of i) {
150
154
  if (u(e)) continue;
151
- let n = e.getBoundingClientRect(), r = t.left - n.left, i = t.top - n.top, s = ne(e);
152
- w(e, v, !1), !(!r && !i) && o.push(ee(e, {
155
+ let n = e.getBoundingClientRect(), r = t.left - n.left, i = t.top - n.top, s = j(e);
156
+ D(e, v, !1), !(!r && !i) && o.push(w(e, {
153
157
  store: v,
154
158
  className: a,
155
- startStyles: { transform: D(`translate(${r}px, ${i}px)`, s) },
159
+ startStyles: { transform: M(`translate(${r}px, ${i}px)`, s) },
156
160
  endStyles: { transform: e.style.transform }
157
161
  }));
158
162
  }
159
163
  return Promise.all(o).then(() => void 0);
160
164
  }
161
- function S(e) {
162
- w(e, y, !1), w(e, v, !1);
165
+ function C(e) {
166
+ D(e, y, !1), D(e, v, !1);
163
167
  }
164
- function ee(e, a) {
168
+ function w(e, a) {
165
169
  let o = Symbol(a.className), s = {
166
170
  transitionDuration: "0s",
167
171
  ...a.startStyles
@@ -171,7 +175,7 @@ function ee(e, a) {
171
175
  }, l = Object.keys({
172
176
  ...s,
173
177
  ...c
174
- }), u = te(e), d, f = new Promise((e) => {
178
+ }), u = T(e), d, f = new Promise((e) => {
175
179
  d = e;
176
180
  }), p = {
177
181
  className: a.className,
@@ -180,12 +184,12 @@ function ee(e, a) {
180
184
  resolve: d
181
185
  };
182
186
  return "transitionDuration" in p.styles && (p.styles.transitionDuration = u), a.store.set(e, p), e.classList.add(a.className), i(e, s), e.getBoundingClientRect(), t().then(async () => {
183
- C(e), a.store.get(e)?.token === o && (await n(e, () => {
187
+ E(e), a.store.get(e)?.token === o && (await n(e, () => {
184
188
  i(e, c);
185
- }), a.store.get(e)?.token === o && T(e, a.store, p, !0));
189
+ }), a.store.get(e)?.token === o && O(e, a.store, p, !0));
186
190
  }), f;
187
191
  }
188
- function te(e) {
192
+ function T(e) {
189
193
  let t = b.get(e);
190
194
  if (t) return t.count += 1, t.value;
191
195
  let n = e.style.transitionDuration;
@@ -194,73 +198,90 @@ function te(e) {
194
198
  count: 1
195
199
  }), n;
196
200
  }
197
- function C(e) {
201
+ function E(e) {
198
202
  let t = b.get(e);
199
203
  t && (--t.count, t.count <= 0 && b.delete(e));
200
204
  }
201
- function w(e, t, n) {
205
+ function D(e, t, n) {
202
206
  let r = t.get(e);
203
- r && T(e, t, r, n);
207
+ r && O(e, t, r, n);
204
208
  }
205
- function T(e, t, n, r) {
206
- E(e, n), t.delete(e), n.resolve(r);
209
+ function O(e, t, n, r) {
210
+ k(e, n), t.delete(e), n.resolve(r);
207
211
  }
208
- function E(e, t) {
212
+ function k(e, t) {
209
213
  e.classList.remove(t.className), i(e, t.styles);
210
214
  }
211
- function ne(e) {
215
+ function j(e) {
212
216
  let t = getComputedStyle(e).transform;
213
217
  return t === "none" ? "" : t;
214
218
  }
215
- function D(...e) {
219
+ function M(...e) {
216
220
  return e.filter((e) => !!e && e !== "none").join(" ");
217
221
  }
218
- function O(e, t, n = {}) {
219
- return A(e), c(e, t, n);
222
+ function N(e, t, n = {}) {
223
+ return I(e), c(e, t, n);
220
224
  }
221
- function re(e, t = {}) {
222
- return O(e, "enter", t);
225
+ function P(e, t = {}) {
226
+ return N(e, "enter", t);
223
227
  }
224
- function k(e, t = {}) {
225
- return O(e, "leave", {
228
+ function F(e, t = {}) {
229
+ return N(e, "leave", {
226
230
  ...t,
227
231
  detachFromLayout: t.detachFromLayout ?? !0
228
232
  });
229
233
  }
230
- function A(e) {
231
- l(e), S(e);
234
+ function I(e) {
235
+ l(e), C(e);
232
236
  }
233
237
  //#endregion
234
238
  //#region src/alerts/alerts.ts
235
- var j = class e extends HTMLElement {
239
+ var AlertsElement = class AlertsElement extends HTMLElement {
236
240
  static duration = 1e4;
237
241
  static politeness = "polite";
238
242
  timeouts = /* @__PURE__ */ new WeakMap();
239
243
  index = 0;
240
244
  connectedCallback() {
241
- this.addEventListener("focusin", this.pauseOnInteraction), this.addEventListener("focusout", this.resumeOnInteraction), this.addEventListener("mouseover", this.pauseOnInteraction), this.addEventListener("mouseout", this.resumeOnInteraction);
242
- for (let e of this.getAlerts()) e.remove(), this.show(e);
245
+ this.addEventListener("focusin", this.pauseOnInteraction);
246
+ this.addEventListener("focusout", this.resumeOnInteraction);
247
+ this.addEventListener("mouseover", this.pauseOnInteraction);
248
+ this.addEventListener("mouseout", this.resumeOnInteraction);
249
+ for (const alert of this.getAlerts()) {
250
+ alert.remove();
251
+ this.show(alert);
252
+ }
243
253
  }
244
254
  disconnectedCallback() {
245
- this.removeEventListener("focusin", this.pauseOnInteraction), this.removeEventListener("focusout", this.resumeOnInteraction), this.removeEventListener("mouseover", this.pauseOnInteraction), this.removeEventListener("mouseout", this.resumeOnInteraction), this.getAlerts().forEach((e) => this.clearTimeout(e));
246
- }
247
- show(e, t = {}) {
248
- let n = t.key || e.dataset.key || String(this.index++);
249
- e.dataset.key = n, this.syncAlertPoliteness(e, t.politeness), t.duration !== void 0 && (e.dataset.duration = String(t.duration));
250
- let r = this.getAlerts().filter((t) => t !== e);
251
- return x(r, () => {
252
- r.filter((e) => e.dataset.key === n).forEach((e) => this.leaveAlert(e)), A(e), this.append(e), re(e);
253
- }), this.startTimeout(e), n;
255
+ this.removeEventListener("focusin", this.pauseOnInteraction);
256
+ this.removeEventListener("focusout", this.resumeOnInteraction);
257
+ this.removeEventListener("mouseover", this.pauseOnInteraction);
258
+ this.removeEventListener("mouseout", this.resumeOnInteraction);
259
+ this.getAlerts().forEach((alert) => this.clearTimeout(alert));
260
+ }
261
+ show(el, options = {}) {
262
+ const key = options.key || el.dataset.key || String(this.index++);
263
+ el.dataset.key = key;
264
+ this.syncAlertPoliteness(el, options.politeness);
265
+ if (options.duration !== void 0) el.dataset.duration = String(options.duration);
266
+ const alerts = this.getAlerts().filter((alert) => alert !== el);
267
+ x(alerts, () => {
268
+ alerts.filter((alert) => alert.dataset.key === key).forEach((alert) => this.leaveAlert(alert));
269
+ I(el);
270
+ this.append(el);
271
+ P(el);
272
+ });
273
+ this.startTimeout(el);
274
+ return key;
254
275
  }
255
- dismiss(e) {
256
- (typeof e == "string" ? this.getAlerts().filter((t) => t.dataset.key === e) : [e]).forEach((e) => this.dismissAlert(e));
276
+ dismiss(elOrKey) {
277
+ (typeof elOrKey === "string" ? this.getAlerts().filter((alert) => alert.dataset.key === elOrKey) : [elOrKey]).forEach((alert) => this.dismissAlert(alert));
257
278
  }
258
279
  clear() {
259
- this.getAlerts().forEach((e) => this.dismissAlert(e));
280
+ this.getAlerts().forEach((alert) => this.dismissAlert(alert));
260
281
  }
261
- speak(e, t = {}) {
262
- let n = document.createElement("div");
263
- Object.assign(n.style, {
282
+ speak(message, options = {}) {
283
+ const el = document.createElement("div");
284
+ Object.assign(el.style, {
264
285
  clip: "rect(0 0 0 0)",
265
286
  clipPath: "inset(50%)",
266
287
  height: "1px",
@@ -268,300 +289,1033 @@ var j = class e extends HTMLElement {
268
289
  position: "absolute",
269
290
  whiteSpace: "nowrap",
270
291
  width: "1px"
271
- }), n.textContent = e, this.show(n, t);
292
+ });
293
+ el.textContent = message;
294
+ this.show(el, options);
272
295
  }
273
- dismissAlert(e) {
274
- x(this.getAlerts().filter((t) => t !== e), () => this.leaveAlert(e));
296
+ dismissAlert(el) {
297
+ x(this.getAlerts().filter((alert) => alert !== el), () => this.leaveAlert(el));
275
298
  }
276
- leaveAlert(e) {
277
- this.clearTimeout(e), k(e).then((t) => {
278
- t && e.parentElement === this && e.remove();
299
+ leaveAlert(el) {
300
+ this.clearTimeout(el);
301
+ F(el).then((complete) => {
302
+ if (complete && el.parentElement === this) el.remove();
279
303
  });
280
304
  }
281
- startTimeout(t) {
282
- this.clearTimeout(t);
283
- let n = Number(t.dataset.duration || e.duration);
284
- n > 0 && this.timeouts.set(t, window.setTimeout(() => this.dismiss(t), n));
305
+ startTimeout(el) {
306
+ this.clearTimeout(el);
307
+ const duration = Number(el.dataset.duration || AlertsElement.duration);
308
+ if (duration > 0) this.timeouts.set(el, window.setTimeout(() => this.dismiss(el), duration));
285
309
  }
286
- clearTimeout(e) {
287
- let t = this.timeouts.get(e);
288
- t !== void 0 && (clearTimeout(t), this.timeouts.delete(e));
310
+ clearTimeout(el) {
311
+ const timeout = this.timeouts.get(el);
312
+ if (timeout !== void 0) {
313
+ clearTimeout(timeout);
314
+ this.timeouts.delete(el);
315
+ }
289
316
  }
290
- pauseOnInteraction = (e) => {
291
- this.handleInteraction(e, (e) => this.clearTimeout(e));
317
+ pauseOnInteraction = (event) => {
318
+ this.handleInteraction(event, (alert) => this.clearTimeout(alert));
292
319
  };
293
- resumeOnInteraction = (e) => {
294
- this.handleInteraction(e, (e) => this.startTimeout(e));
320
+ resumeOnInteraction = (event) => {
321
+ this.handleInteraction(event, (alert) => this.startTimeout(alert));
295
322
  };
296
- handleInteraction(e, t) {
297
- let n = this.getAlertFromTarget(e.target);
298
- n && (e.relatedTarget instanceof Node && n.contains(e.relatedTarget) || t(n));
323
+ handleInteraction(event, action) {
324
+ const alert = this.getAlertFromTarget(event.target);
325
+ if (!alert) return;
326
+ if (event.relatedTarget instanceof Node && alert.contains(event.relatedTarget)) return;
327
+ action(alert);
299
328
  }
300
329
  getAlerts() {
301
- return Array.from(this.children, (e) => e);
330
+ return Array.from(this.children, (child) => child);
302
331
  }
303
- syncAlertPoliteness(t, n) {
304
- if ((n || this.getAuthoredPoliteness(t) || e.politeness) === "assertive") {
305
- t.setAttribute("role", "alert"), t.setAttribute("aria-live", "assertive");
332
+ syncAlertPoliteness(el, politeness) {
333
+ if ((politeness || this.getAuthoredPoliteness(el) || AlertsElement.politeness) === "assertive") {
334
+ el.setAttribute("role", "alert");
335
+ el.setAttribute("aria-live", "assertive");
306
336
  return;
307
337
  }
308
- t.setAttribute("role", "status"), t.setAttribute("aria-live", "polite");
338
+ el.setAttribute("role", "status");
339
+ el.setAttribute("aria-live", "polite");
309
340
  }
310
- getAuthoredPoliteness(e) {
311
- if (e.getAttribute("role") === "alert" || e.getAttribute("aria-live") === "assertive") return "assertive";
312
- if (e.getAttribute("role") === "status" || e.getAttribute("aria-live") === "polite") return "polite";
341
+ getAuthoredPoliteness(el) {
342
+ if (el.getAttribute("role") === "alert" || el.getAttribute("aria-live") === "assertive") return "assertive";
343
+ if (el.getAttribute("role") === "status" || el.getAttribute("aria-live") === "polite") return "polite";
313
344
  }
314
- getAlertFromTarget(e) {
315
- return e instanceof Node && Array.from(this.children).find((t) => t instanceof HTMLElement && t.contains(e)) || null;
345
+ getAlertFromTarget(target) {
346
+ if (!(target instanceof Node)) return null;
347
+ return Array.from(this.children).find((child) => child instanceof HTMLElement && child.contains(target)) || null;
316
348
  }
317
349
  };
318
350
  //#endregion
319
351
  //#region src/utils.ts
320
- function M(e, t) {
321
- let n = !1;
352
+ function createQueuedSync(element, sync) {
353
+ let queued = false;
354
+ const queue = () => {
355
+ if (queued) return;
356
+ queued = true;
357
+ queueMicrotask(() => {
358
+ queued = false;
359
+ if (element.isConnected) sync();
360
+ });
361
+ };
322
362
  return {
323
- queue: () => {
324
- n || (n = !0, queueMicrotask(() => {
325
- n = !1, e.isConnected && t();
326
- }));
327
- },
363
+ queue,
328
364
  disconnect() {
329
- n = !1;
365
+ queued = false;
330
366
  }
331
367
  };
332
368
  }
333
- function N(e, t, n) {
334
- let r = M(e, n), i = new MutationObserver(r.queue);
369
+ function createQueuedElementSync(element, options, sync) {
370
+ const queuedSync = createQueuedSync(element, sync);
371
+ const observer = new MutationObserver(queuedSync.queue);
335
372
  return {
336
373
  observe() {
337
- i.observe(e, t);
374
+ observer.observe(element, options);
338
375
  },
339
376
  disconnect() {
340
- i.disconnect(), r.disconnect();
377
+ observer.disconnect();
378
+ queuedSync.disconnect();
341
379
  },
342
- queue: r.queue
380
+ queue: queuedSync.queue
343
381
  };
344
382
  }
345
- function P(e) {
346
- let t = e.getRootNode();
347
- return t instanceof ShadowRoot ? t : e.ownerDocument;
383
+ function getLookupRoot(element) {
384
+ const root = element.getRootNode();
385
+ return root instanceof ShadowRoot ? root : element.ownerDocument;
348
386
  }
349
- function F(e, t) {
350
- let { currentIndex: n, length: r, vertical: i } = t;
351
- if (!(r === 0 || n < 0 || n >= r)) {
352
- if (e === (i ? "ArrowUp" : "ArrowLeft")) return (n - 1 + r) % r;
353
- if (e === (i ? "ArrowDown" : "ArrowRight")) return (n + 1) % r;
354
- if (e === "Home") return 0;
355
- if (e === "End") return r - 1;
356
- }
387
+ function getRovingIndexForKey(key, options) {
388
+ const { currentIndex, length, vertical } = options;
389
+ if (length === 0 || currentIndex < 0 || currentIndex >= length) return;
390
+ if (key === (vertical ? "ArrowUp" : "ArrowLeft")) return (currentIndex - 1 + length) % length;
391
+ if (key === (vertical ? "ArrowDown" : "ArrowRight")) return (currentIndex + 1) % length;
392
+ if (key === "Home") return 0;
393
+ if (key === "End") return length - 1;
357
394
  }
358
395
  //#endregion
396
+ //#region src/combobox/combobox.ts
397
+ let idCounter$1 = 0;
398
+ const internalSourceEvents = /* @__PURE__ */ new WeakSet();
399
+ const transferredAttributes = [
400
+ "title",
401
+ "aria-label",
402
+ "aria-labelledby",
403
+ "aria-describedby",
404
+ "aria-errormessage"
405
+ ];
406
+ var ComboboxElement = class extends HTMLElement {
407
+ idPrefix = "combobox" + ++idCounter$1;
408
+ suppressedListId = this.idPrefix + "_suppressed_list";
409
+ sync = createQueuedSync(this, () => this.sourceState ? this.render() : this.enhance());
410
+ observer = new MutationObserver(this.sync.queue);
411
+ listeners;
412
+ sourceState;
413
+ control;
414
+ tokens;
415
+ input;
416
+ listbox;
417
+ activeIndex = -1;
418
+ labelledBy = "";
419
+ generatedLabelIds = [];
420
+ connectedCallback() {
421
+ this.sync.queue();
422
+ }
423
+ disconnectedCallback() {
424
+ this.sync.disconnect();
425
+ this.teardownSource();
426
+ }
427
+ refresh() {
428
+ const transferFocus = this.input?.matches(":focus");
429
+ this.teardownSource();
430
+ if (this.isConnected) this.enhance(transferFocus);
431
+ }
432
+ enhance(transferFocus) {
433
+ if (typeof HTMLElement.prototype.showPopover !== "function" || typeof HTMLElement.prototype.hidePopover !== "function") return;
434
+ const source = this.discoverSource();
435
+ if (!source) return;
436
+ transferFocus ??= source.matches(":focus");
437
+ this.setupSource(source);
438
+ this.render();
439
+ if (transferFocus) this.input?.focus();
440
+ }
441
+ setupSource(source) {
442
+ const signal = (this.listeners = new AbortController()).signal;
443
+ if (source instanceof HTMLSelectElement) {
444
+ const container = document.createElement("div");
445
+ this.sourceState = {
446
+ source,
447
+ cssHidden: source.style.display === "none" || !source.hidden && getComputedStyle(source).display === "none",
448
+ container
449
+ };
450
+ container.hidden = true;
451
+ container.inert = true;
452
+ source.before(container);
453
+ container.append(source);
454
+ this.createGeneratedInput(source, signal);
455
+ } else {
456
+ this.sourceState = this.createInputState(source);
457
+ this.input = source;
458
+ this.addInputListeners(source, signal);
459
+ source.addEventListener("keydown", this.onWidgetKeyDown, { signal });
460
+ source.addEventListener("focusout", this.onFocusOut, { signal });
461
+ source.setAttribute("list", this.suppressedListId);
462
+ this.observeDatalist();
463
+ }
464
+ const listbox = this.createListbox(signal);
465
+ this.setInputAttribute("role", "combobox");
466
+ this.setInputAttribute("aria-autocomplete", "list");
467
+ this.setInputAttribute("aria-haspopup", "listbox");
468
+ this.setInputAttribute("aria-controls", listbox.id);
469
+ if (this.multiple) listbox.setAttribute("aria-multiselectable", "true");
470
+ source.addEventListener("input", this.onSourceUpdate, { signal });
471
+ source.addEventListener("change", this.onSourceUpdate, { signal });
472
+ source.addEventListener("invalid", () => this.syncValidityState(), { signal });
473
+ this.ownerDocument.addEventListener("pointerdown", this.onDocumentPointerDown, {
474
+ capture: true,
475
+ signal
476
+ });
477
+ this.observeSource(source);
478
+ source.form?.addEventListener("reset", this.onFormReset, { signal });
479
+ if (source instanceof HTMLSelectElement) {
480
+ const labels = Array.from(source.labels);
481
+ this.labelledBy = labels.map((label, index) => {
482
+ if (label.id) return label.id;
483
+ const id = `${this.idPrefix}_label_${index}`;
484
+ label.id = id;
485
+ this.generatedLabelIds.push([label, id]);
486
+ return id;
487
+ }).join(" ");
488
+ labels.forEach((label) => {
489
+ label.addEventListener("click", this.onLabelClick, { signal });
490
+ });
491
+ }
492
+ }
493
+ observeSource(source) {
494
+ this.observer.observe(source, {
495
+ subtree: source instanceof HTMLSelectElement,
496
+ childList: source instanceof HTMLSelectElement,
497
+ characterData: source instanceof HTMLSelectElement,
498
+ attributes: true,
499
+ attributeFilter: [
500
+ "disabled",
501
+ "hidden",
502
+ "label",
503
+ "readonly",
504
+ "required",
505
+ "selected",
506
+ "tabindex",
507
+ "value",
508
+ "aria-invalid",
509
+ ...transferredAttributes
510
+ ]
511
+ });
512
+ for (let ancestor = source.parentElement; ancestor; ancestor = ancestor.parentElement) if (ancestor instanceof HTMLFieldSetElement) this.observer.observe(ancestor, {
513
+ attributes: true,
514
+ attributeFilter: ["disabled"]
515
+ });
516
+ }
517
+ teardownSource() {
518
+ const state = this.sourceState;
519
+ if (!state) return;
520
+ this.listeners?.abort();
521
+ this.listeners = void 0;
522
+ this.observer.disconnect();
523
+ this.generatedLabelIds.forEach(([label, id]) => {
524
+ if (label.id === id) label.removeAttribute("id");
525
+ });
526
+ this.generatedLabelIds = [];
527
+ this.labelledBy = "";
528
+ if (!("cssHidden" in state)) {
529
+ const list = state.source.getAttribute("list");
530
+ if (list !== this.suppressedListId) state.list = list;
531
+ this.restoreInputAttributes(state.source, state.inputAttributes);
532
+ if (state.list !== null) state.source.setAttribute("list", state.list);
533
+ else state.source.removeAttribute("list");
534
+ } else state.container.replaceWith(...state.container.childNodes);
535
+ this.control?.remove();
536
+ this.listbox?.remove();
537
+ this.sourceState = void 0;
538
+ this.control = void 0;
539
+ this.tokens = void 0;
540
+ this.input = void 0;
541
+ this.listbox = void 0;
542
+ this.activeIndex = -1;
543
+ }
544
+ render() {
545
+ const state = this.sourceState;
546
+ if (!state) return;
547
+ if ("cssHidden" in state && this.control) this.control.hidden = this.sourceHidden;
548
+ this.syncInputState();
549
+ if (state.source instanceof HTMLSelectElement) {
550
+ this.syncInputDisplay();
551
+ this.renderTokens();
552
+ }
553
+ this.renderOptions();
554
+ }
555
+ createGeneratedInput(source, signal) {
556
+ this.control = document.createElement("div");
557
+ this.control.setAttribute("data-combobox-control", "");
558
+ this.control.addEventListener("focusout", this.onFocusOut, { signal });
559
+ this.control.addEventListener("mousedown", this.onControlMouseDown, { signal });
560
+ this.control.addEventListener("click", this.onControlClick, { signal });
561
+ this.control.addEventListener("keydown", this.onWidgetKeyDown, { signal });
562
+ this.append(this.control);
563
+ if (this.multiple) {
564
+ this.tokens = document.createElement("div");
565
+ this.tokens.setAttribute("data-combobox-tokens", "");
566
+ this.control.append(this.tokens);
567
+ }
568
+ this.input = document.createElement("input");
569
+ this.input.type = "text";
570
+ const form = source.getAttribute("form");
571
+ if (form !== null) this.input.setAttribute("form", form);
572
+ this.addInputListeners(this.input, signal);
573
+ this.control.append(this.input);
574
+ }
575
+ createListbox(signal) {
576
+ this.listbox = document.createElement("div");
577
+ this.listbox.id = this.idPrefix + "_listbox";
578
+ this.listbox.setAttribute("role", "listbox");
579
+ this.listbox.setAttribute("popover", "manual");
580
+ this.listbox.addEventListener("mousedown", (e) => {
581
+ if (e.target?.closest("[role=\"option\"]")) e.preventDefault();
582
+ }, { signal });
583
+ this.listbox.addEventListener("click", this.onListboxClick, { signal });
584
+ this.append(this.listbox);
585
+ return this.listbox;
586
+ }
587
+ syncInputState() {
588
+ const state = this.sourceState;
589
+ const input = this.input;
590
+ if (!state || !input) return;
591
+ this.setInputAttribute("aria-expanded", String(this.isOpen()));
592
+ if (state.source instanceof HTMLSelectElement) {
593
+ transferredAttributes.forEach((attribute) => {
594
+ this.setInputAttribute(attribute, state.source.getAttribute(attribute));
595
+ });
596
+ if (!state.source.hasAttribute("aria-label") && !state.source.hasAttribute("aria-labelledby") && this.labelledBy) input.setAttribute("aria-labelledby", this.labelledBy);
597
+ input.disabled = state.source.disabled;
598
+ input.tabIndex = state.source.tabIndex;
599
+ this.setInputAttribute("aria-required", state.source.required ? "true" : null);
600
+ }
601
+ this.syncValidityState();
602
+ if (!this.editable) this.close();
603
+ }
604
+ syncValidityState() {
605
+ const source = this.sourceState?.source;
606
+ if (!(source instanceof HTMLSelectElement) || !this.input) return;
607
+ this.input.setCustomValidity(source.validity.valid ? "" : source.validationMessage);
608
+ const invalid = source.getAttribute("aria-invalid") ?? (!source.validity.valid ? "true" : null);
609
+ this.setInputAttribute("aria-invalid", invalid);
610
+ }
611
+ addInputListeners(input, signal) {
612
+ input.addEventListener("input", this.onInput, { signal });
613
+ input.addEventListener("keydown", this.onKeyDown, { signal });
614
+ input.addEventListener("focus", this.onInputFocus, { signal });
615
+ input.addEventListener("click", this.onInputClick, { signal });
616
+ }
617
+ restoreInputAttributes(input, attributes) {
618
+ attributes.forEach(({ original, managed }, name) => {
619
+ if (input.getAttribute(name) !== managed) return;
620
+ if (original === null) input.removeAttribute(name);
621
+ else input.setAttribute(name, original);
622
+ });
623
+ }
624
+ setInputAttribute(name, value) {
625
+ const input = this.input;
626
+ const state = this.sourceState;
627
+ if (!input || !state) return;
628
+ if (!("cssHidden" in state)) {
629
+ const attribute = state.inputAttributes.get(name);
630
+ if (attribute) attribute.managed = value;
631
+ }
632
+ if (value === null) input.removeAttribute(name);
633
+ else input.setAttribute(name, value);
634
+ }
635
+ renderTokens() {
636
+ const source = this.sourceState?.source;
637
+ if (!this.tokens || !(source instanceof HTMLSelectElement)) return;
638
+ const selectedOptions = Array.from(source.selectedOptions).filter((option) => option.value !== "");
639
+ this.tokens.replaceChildren(...selectedOptions.map((option) => {
640
+ const token = document.createElement("span");
641
+ token.setAttribute("data-combobox-token", "");
642
+ const label = this.optionLabel(option);
643
+ token.textContent = label + " ";
644
+ const remove = document.createElement("button");
645
+ remove.type = "button";
646
+ remove.setAttribute("data-combobox-token-remove", "");
647
+ remove.dataset.optionIndex = String(option.index);
648
+ remove.setAttribute("aria-label", `Remove ${label}`);
649
+ remove.disabled = source.disabled || this.isOptionDisabled(option);
650
+ remove.tabIndex = -1;
651
+ remove.textContent = "×";
652
+ token.append(remove);
653
+ return token;
654
+ }));
655
+ }
656
+ renderOptions() {
657
+ if (!this.listbox) return;
658
+ const options = this.filteredOptions();
659
+ if (this.activeIndex >= options.length) this.activeIndex = this.firstEnabledIndex(options);
660
+ const children = [];
661
+ const groups = /* @__PURE__ */ new Map();
662
+ options.forEach((option, index) => {
663
+ const el = document.createElement("div");
664
+ el.id = this.idPrefix + "_option_" + index;
665
+ el.dataset.index = String(index);
666
+ el.setAttribute("role", "option");
667
+ el.setAttribute("aria-selected", String(this.isSelected(option)));
668
+ el.textContent = this.optionLabel(option);
669
+ if (!this.multiple && option.value === "") el.setAttribute("data-placeholder", "");
670
+ if (this.isOptionDisabled(option)) el.setAttribute("aria-disabled", "true");
671
+ if (index === this.activeIndex) el.setAttribute("data-active", "");
672
+ const parent = option.parentElement;
673
+ if (parent instanceof HTMLOptGroupElement) {
674
+ let group = groups.get(parent);
675
+ if (!group) {
676
+ group = document.createElement("div");
677
+ group.setAttribute("role", "group");
678
+ group.setAttribute("aria-label", parent.label);
679
+ groups.set(parent, group);
680
+ children.push(group);
681
+ }
682
+ group.append(el);
683
+ } else children.push(el);
684
+ });
685
+ this.listbox.replaceChildren(...children);
686
+ if (!options.length) {
687
+ this.close();
688
+ return;
689
+ }
690
+ this.syncActiveDescendant();
691
+ }
692
+ syncInputDisplay() {
693
+ const state = this.sourceState;
694
+ if (!this.input || !(state?.source instanceof HTMLSelectElement)) return;
695
+ if (this.input.matches(":focus") && (this.multiple || this.isOpen())) return;
696
+ this.restoreCommittedText();
697
+ }
698
+ onInput = () => {
699
+ if (!this.editable) return;
700
+ this.activeIndex = this.firstEnabledIndex(this.filteredOptions());
701
+ this.renderOptions();
702
+ this.open();
703
+ };
704
+ onInputFocus = () => {
705
+ this.syncValidityState();
706
+ this.showSuggestions();
707
+ };
708
+ onInputClick = () => {
709
+ if (!this.isOpen()) this.showSuggestions();
710
+ };
711
+ onKeyDown = (e) => {
712
+ if (e.isComposing || !this.input || !this.editable) return;
713
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
714
+ e.preventDefault();
715
+ if (!this.isOpen() && this.sourceState?.source instanceof HTMLSelectElement) this.showSuggestions();
716
+ this.moveActive(e.key === "ArrowDown" ? 1 : -1);
717
+ this.open();
718
+ return;
719
+ }
720
+ if (e.key === "Enter" && this.isOpen()) {
721
+ e.preventDefault();
722
+ this.chooseOption(this.filteredOptions()[this.activeIndex]);
723
+ return;
724
+ }
725
+ if (this.multiple && this.input.selectionStart === 0 && this.input.selectionEnd === 0 && (e.key === "ArrowLeft" || e.key === "Backspace" && this.input.value === "")) {
726
+ const lastToken = this.enabledTokenButtons().at(-1);
727
+ if (lastToken) {
728
+ e.preventDefault();
729
+ lastToken.focus();
730
+ }
731
+ }
732
+ };
733
+ onControlMouseDown = (e) => {
734
+ if (e.target?.closest("[data-combobox-token]")) e.preventDefault();
735
+ };
736
+ onControlClick = (e) => {
737
+ const target = e.target;
738
+ const remove = target?.closest("[data-combobox-token-remove]");
739
+ if (remove) {
740
+ const option = this.optionForToken(remove);
741
+ if (option) this.toggleOption(option);
742
+ this.input?.focus();
743
+ return;
744
+ }
745
+ const token = target?.closest("[data-combobox-token]");
746
+ if (token) {
747
+ token.querySelector("[data-combobox-token-remove]")?.focus();
748
+ return;
749
+ }
750
+ this.input?.focus();
751
+ if (!this.isOpen()) this.showSuggestions();
752
+ };
753
+ onWidgetKeyDown = (e) => {
754
+ if (e.isComposing) return;
755
+ if (e.key === "Escape" && this.isOpen()) {
756
+ e.preventDefault();
757
+ e.stopPropagation();
758
+ this.dismiss();
759
+ return;
760
+ }
761
+ const target = e.target;
762
+ const tokenFocused = target instanceof HTMLButtonElement && target.hasAttribute("data-combobox-token-remove");
763
+ if (e.key === "Tab") {
764
+ if (tokenFocused) this.input?.focus();
765
+ this.close();
766
+ return;
767
+ }
768
+ if (!tokenFocused) return;
769
+ const tokens = this.enabledTokenButtons();
770
+ const index = tokens.indexOf(target);
771
+ if (e.key === "ArrowLeft" && index > 0) {
772
+ e.preventDefault();
773
+ tokens[index - 1].focus();
774
+ return;
775
+ }
776
+ if (e.key === "ArrowRight") {
777
+ e.preventDefault();
778
+ (tokens[index + 1] ?? this.input)?.focus();
779
+ return;
780
+ }
781
+ if (e.key === "Backspace" || e.key === "Delete") {
782
+ e.preventDefault();
783
+ const option = this.optionForToken(target);
784
+ if (!option) return;
785
+ this.toggleOption(option);
786
+ const remaining = this.enabledTokenButtons();
787
+ (remaining[e.key === "Backspace" ? index - 1 : Math.min(index, remaining.length - 1)] ?? this.input)?.focus();
788
+ }
789
+ };
790
+ onListboxClick = (e) => {
791
+ const optionEl = e.target?.closest("[role=\"option\"]");
792
+ if (!optionEl) return;
793
+ if (this.chooseOption(this.filteredOptions()[Number(optionEl.dataset.index)])) this.input?.focus();
794
+ };
795
+ onFocusOut = (e) => {
796
+ const next = e.relatedTarget;
797
+ if (next instanceof Node && this.contains(next)) return;
798
+ this.dismiss();
799
+ };
800
+ onDocumentPointerDown = (e) => {
801
+ if (!this.isOpen() || e.composedPath().includes(this)) return;
802
+ this.dismiss();
803
+ };
804
+ onLabelClick = (e) => {
805
+ if (e.defaultPrevented || e.target instanceof Element && !!e.target.closest("a[href], button, input, select, textarea, summary, [contenteditable]")) return;
806
+ e.preventDefault();
807
+ if (!(e.target instanceof Node && this.contains(e.target))) this.input?.focus();
808
+ };
809
+ onSourceUpdate = (event) => {
810
+ if (!internalSourceEvents.has(event)) this.sync.queue();
811
+ };
812
+ onFormReset = () => {
813
+ queueMicrotask(() => {
814
+ this.close();
815
+ this.sync.queue();
816
+ });
817
+ };
818
+ moveActive(delta) {
819
+ const options = this.filteredOptions();
820
+ if (!options.length) {
821
+ this.activeIndex = -1;
822
+ this.syncActiveDescendant();
823
+ return;
824
+ }
825
+ let index = this.activeIndex === -1 && delta === -1 ? options.length : this.activeIndex;
826
+ for (let i = 0; i < options.length; i++) {
827
+ index = (index + delta + options.length) % options.length;
828
+ if (!this.isOptionDisabled(options[index])) {
829
+ this.activeIndex = index;
830
+ this.renderOptions();
831
+ return;
832
+ }
833
+ }
834
+ }
835
+ showSuggestions() {
836
+ const state = this.sourceState;
837
+ if (!state || !this.input || !this.editable) return;
838
+ if (state.source instanceof HTMLSelectElement) this.input.value = "";
839
+ const options = this.filteredOptions();
840
+ const selectedIndex = options.findIndex((option) => this.isSelected(option) && !this.isOptionDisabled(option));
841
+ this.activeIndex = state.source instanceof HTMLSelectElement && selectedIndex !== -1 ? selectedIndex : this.firstEnabledIndex(options);
842
+ this.renderOptions();
843
+ this.open();
844
+ }
845
+ chooseOption(option) {
846
+ const state = this.sourceState;
847
+ if (!state || !option || !this.editable || this.isOptionDisabled(option)) return false;
848
+ if (this.multiple) {
849
+ this.toggleOption(option);
850
+ return true;
851
+ }
852
+ if (state.source instanceof HTMLSelectElement) {
853
+ if (!option.selected) {
854
+ option.selected = true;
855
+ this.emitSourceUpdate(state.source);
856
+ }
857
+ } else {
858
+ if (state.source.value !== option.value) state.source.value = option.value;
859
+ this.emitSourceUpdate(state.source);
860
+ }
861
+ this.syncValidityState();
862
+ this.dismiss();
863
+ return true;
864
+ }
865
+ toggleOption(option) {
866
+ const state = this.sourceState;
867
+ if (!(state?.source instanceof HTMLSelectElement) || !this.editable || this.isOptionDisabled(option)) return;
868
+ option.selected = !option.selected;
869
+ this.emitSourceUpdate(state.source);
870
+ this.syncValidityState();
871
+ if (this.input) this.input.value = "";
872
+ this.activeIndex = this.firstEnabledIndex(this.filteredOptions());
873
+ this.renderTokens();
874
+ this.renderOptions();
875
+ }
876
+ emitSourceUpdate(source) {
877
+ for (const type of ["input", "change"]) {
878
+ const event = new Event(type, {
879
+ bubbles: true,
880
+ composed: type === "input"
881
+ });
882
+ internalSourceEvents.add(event);
883
+ source.dispatchEvent(event);
884
+ }
885
+ }
886
+ restoreCommittedText() {
887
+ const state = this.sourceState;
888
+ if (!this.input || !(state?.source instanceof HTMLSelectElement)) return;
889
+ if (this.multiple) {
890
+ this.input.value = "";
891
+ return;
892
+ }
893
+ const selected = state.source.options.item(state.source.selectedIndex);
894
+ const label = selected ? this.optionLabel(selected) : "";
895
+ this.input.placeholder = label;
896
+ this.input.value = selected?.value ? label : "";
897
+ }
898
+ open() {
899
+ if (!this.listbox || !this.input) return;
900
+ if (!this.listbox.childElementCount) {
901
+ this.close();
902
+ return;
903
+ }
904
+ const wasOpen = this.isOpen();
905
+ this.setInputAttribute("aria-expanded", "true");
906
+ if (!wasOpen) {
907
+ const source = this.control ?? this.input;
908
+ this.listbox.showPopover({ source });
909
+ }
910
+ this.syncActiveDescendant();
911
+ if (wasOpen) this.scrollActiveOptionIntoView();
912
+ else requestAnimationFrame(() => this.scrollActiveOptionIntoView());
913
+ }
914
+ close() {
915
+ if (!this.listbox || !this.input) return;
916
+ if (this.isOpen()) this.listbox.hidePopover();
917
+ this.setInputAttribute("aria-expanded", "false");
918
+ this.activeIndex = -1;
919
+ this.syncActiveDescendant();
920
+ }
921
+ dismiss() {
922
+ this.close();
923
+ this.restoreCommittedText();
924
+ }
925
+ isOpen() {
926
+ return this.listbox?.matches(":popover-open") ?? false;
927
+ }
928
+ get activeOption() {
929
+ return this.listbox?.querySelector(`[role="option"][data-index="${this.activeIndex}"]`) ?? void 0;
930
+ }
931
+ syncActiveDescendant() {
932
+ if (!this.input) return;
933
+ const option = this.activeOption;
934
+ if (this.isOpen() && option) this.setInputAttribute("aria-activedescendant", option.id);
935
+ else this.setInputAttribute("aria-activedescendant", null);
936
+ }
937
+ scrollActiveOptionIntoView() {
938
+ const listbox = this.listbox;
939
+ const option = this.activeOption;
940
+ if (!listbox || !option || !this.isOpen() || !listbox.clientHeight) return;
941
+ const listboxRect = listbox.getBoundingClientRect();
942
+ const optionRect = option.getBoundingClientRect();
943
+ const visibleTop = listboxRect.top + listbox.clientTop;
944
+ const visibleBottom = visibleTop + listbox.clientHeight;
945
+ if (optionRect.top < visibleTop) listbox.scrollTop -= visibleTop - optionRect.top;
946
+ else if (optionRect.bottom > visibleBottom) listbox.scrollTop += optionRect.bottom - visibleBottom;
947
+ }
948
+ enabledTokenButtons() {
949
+ return this.tokens ? Array.from(this.tokens.querySelectorAll("[data-combobox-token-remove]:not(:disabled)")) : [];
950
+ }
951
+ optionForToken(token) {
952
+ const source = this.sourceState?.source;
953
+ return source instanceof HTMLSelectElement ? source.options.item(Number(token.dataset.optionIndex)) : null;
954
+ }
955
+ filteredOptions() {
956
+ const query = this.input?.value.trim().toLowerCase() ?? "";
957
+ return this.options().filter((option) => {
958
+ if (!query) return true;
959
+ return this.optionLabel(option).toLowerCase().includes(query) || option.value.toLowerCase().includes(query);
960
+ });
961
+ }
962
+ options() {
963
+ const state = this.sourceState;
964
+ if (!state) return [];
965
+ if (state.source instanceof HTMLSelectElement) return Array.from(state.source.options).filter((option) => (!this.multiple || option.value !== "" && !option.selected) && !!this.optionLabel(option).trim() && !option.hidden && !(option.parentElement instanceof HTMLOptGroupElement && option.parentElement.hidden));
966
+ const datalist = "datalist" in state ? state.datalist : null;
967
+ return datalist ? Array.from(datalist.options).filter((option) => !option.hidden) : [];
968
+ }
969
+ firstEnabledIndex(options) {
970
+ return options.findIndex((option) => !this.isOptionDisabled(option));
971
+ }
972
+ isOptionDisabled(option) {
973
+ return option.disabled || option.parentElement instanceof HTMLOptGroupElement && option.parentElement.disabled;
974
+ }
975
+ optionLabel(option) {
976
+ return this.sourceState?.source instanceof HTMLInputElement ? option.label || option.value || option.textContent || "" : option.label || option.textContent || option.value;
977
+ }
978
+ isSelected(option) {
979
+ const source = this.sourceState?.source;
980
+ return source instanceof HTMLInputElement ? source.value === option.value : option.selected;
981
+ }
982
+ observeDatalist() {
983
+ const state = this.sourceState;
984
+ const datalist = state && "datalist" in state ? state.datalist : null;
985
+ if (!datalist) return;
986
+ this.observer.observe(datalist, {
987
+ subtree: true,
988
+ childList: true,
989
+ characterData: true,
990
+ attributes: true,
991
+ attributeFilter: [
992
+ "disabled",
993
+ "hidden",
994
+ "label",
995
+ "value"
996
+ ]
997
+ });
998
+ }
999
+ discoverSource() {
1000
+ const candidates = Array.from(this.children).filter((child) => this.isSupportedSource(child));
1001
+ return candidates.length === 1 ? candidates[0] : void 0;
1002
+ }
1003
+ isSupportedSource(element) {
1004
+ if (element instanceof HTMLSelectElement) return true;
1005
+ return element instanceof HTMLInputElement && [
1006
+ "text",
1007
+ "search",
1008
+ "email",
1009
+ "url",
1010
+ "tel"
1011
+ ].includes(element.type) && !(element.type === "email" && element.multiple) && !!element.getAttribute("list");
1012
+ }
1013
+ get multiple() {
1014
+ const source = this.sourceState?.source;
1015
+ return source instanceof HTMLSelectElement && source.multiple;
1016
+ }
1017
+ get editable() {
1018
+ const source = this.sourceState?.source;
1019
+ return !!(source && !this.sourceHidden && !source.matches(":disabled") && !(source instanceof HTMLInputElement && source.readOnly));
1020
+ }
1021
+ get sourceHidden() {
1022
+ const state = this.sourceState;
1023
+ return !!(state && (state.source.hidden || "cssHidden" in state && state.cssHidden));
1024
+ }
1025
+ snapshotInputAttributes(input) {
1026
+ return new Map([
1027
+ "role",
1028
+ "aria-autocomplete",
1029
+ "aria-haspopup",
1030
+ "aria-expanded",
1031
+ "aria-controls",
1032
+ "aria-activedescendant"
1033
+ ].map((name) => {
1034
+ const value = input.getAttribute(name);
1035
+ return [name, {
1036
+ original: value,
1037
+ managed: value
1038
+ }];
1039
+ }));
1040
+ }
1041
+ createInputState(source) {
1042
+ const list = source.getAttribute("list");
1043
+ const datalist = getLookupRoot(this).querySelector(`#${CSS.escape(list)}`);
1044
+ return {
1045
+ source,
1046
+ list,
1047
+ datalist: datalist instanceof HTMLDataListElement ? datalist : null,
1048
+ inputAttributes: this.snapshotInputAttributes(source)
1049
+ };
1050
+ }
1051
+ };
1052
+ //#endregion
359
1053
  //#region src/menu/menu.ts
360
- var I = class e extends HTMLElement {
1054
+ var MenuElement = class MenuElement extends HTMLElement {
361
1055
  static searchDelay = 800;
362
1056
  static observedAttributes = ["id", "popover"];
363
1057
  itemSync;
364
1058
  search = "";
365
1059
  searchTimeout;
366
1060
  connectedCallback() {
367
- this.hasAttribute("role") || this.setAttribute("role", "menu"), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "-1"), this.addEventListener("keydown", this.onKeyDown), this.addEventListener("click", this.onClick), this.addEventListener("mouseenter", this.onMouseEnter, !0), this.itemSync ??= N(this, {
368
- subtree: !0,
369
- childList: !0,
370
- attributes: !0,
1061
+ if (!this.hasAttribute("role")) this.setAttribute("role", "menu");
1062
+ if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "-1");
1063
+ this.addEventListener("keydown", this.onKeyDown);
1064
+ this.addEventListener("click", this.onClick);
1065
+ this.addEventListener("mouseenter", this.onMouseEnter, true);
1066
+ this.itemSync ??= createQueuedElementSync(this, {
1067
+ subtree: true,
1068
+ childList: true,
1069
+ attributes: true,
371
1070
  attributeFilter: ["role", "tabindex"]
372
- }, () => this.syncItems()), this.itemSync.observe(), this.itemSync.queue(), this.syncDocumentListeners();
1071
+ }, () => this.syncItems());
1072
+ this.itemSync.observe();
1073
+ this.itemSync.queue();
1074
+ this.syncDocumentListeners();
373
1075
  }
374
1076
  disconnectedCallback() {
375
- this.removeEventListener("keydown", this.onKeyDown), this.removeEventListener("click", this.onClick), this.removeEventListener("mouseenter", this.onMouseEnter, !0), this.removeDocumentListeners(), this.itemSync?.disconnect(), this.closeSelfAndDescendants(), clearTimeout(this.searchTimeout);
1077
+ this.removeEventListener("keydown", this.onKeyDown);
1078
+ this.removeEventListener("click", this.onClick);
1079
+ this.removeEventListener("mouseenter", this.onMouseEnter, true);
1080
+ this.removeDocumentListeners();
1081
+ this.itemSync?.disconnect();
1082
+ this.closeSelfAndDescendants();
1083
+ clearTimeout(this.searchTimeout);
376
1084
  }
377
- attributeChangedCallback(e, t, n) {
378
- t !== n && (e !== "id" && e !== "popover" || this.syncDocumentListeners());
1085
+ attributeChangedCallback(name, oldValue, newValue) {
1086
+ if (oldValue === newValue) return;
1087
+ if (name !== "id" && name !== "popover") return;
1088
+ this.syncDocumentListeners();
379
1089
  }
380
1090
  get horizontal() {
381
1091
  return this.getAttribute("aria-orientation") === "horizontal";
382
1092
  }
383
1093
  syncDocumentListeners() {
384
1094
  if (this.isConnected && this.hasAttribute("popover") && !this.getParentMenuTrigger()) {
385
- this.ownerDocument.addEventListener("click", this.onDocumentClick), this.ownerDocument.addEventListener("keydown", this.onDocumentKeyDown);
1095
+ this.ownerDocument.addEventListener("click", this.onDocumentClick);
1096
+ this.ownerDocument.addEventListener("keydown", this.onDocumentKeyDown);
386
1097
  return;
387
1098
  }
388
1099
  this.removeDocumentListeners();
389
1100
  }
390
1101
  removeDocumentListeners() {
391
- this.ownerDocument.removeEventListener("click", this.onDocumentClick), this.ownerDocument.removeEventListener("keydown", this.onDocumentKeyDown);
1102
+ this.ownerDocument.removeEventListener("click", this.onDocumentClick);
1103
+ this.ownerDocument.removeEventListener("keydown", this.onDocumentKeyDown);
392
1104
  }
393
1105
  onDocumentClick = (e) => {
394
- this.getRootTriggerForEvent(e) && requestAnimationFrame(() => {
395
- this.isActive() && (e.detail === 0 ? this.getEnabledItems()[0]?.focus() : this.focus({ preventScroll: !0 }));
1106
+ if (!this.getRootTriggerForEvent(e)) return;
1107
+ requestAnimationFrame(() => {
1108
+ if (!this.isActive()) return;
1109
+ if (e.detail === 0) this.getEnabledItems()[0]?.focus();
1110
+ else this.focus({ preventScroll: true });
396
1111
  });
397
1112
  };
398
1113
  onDocumentKeyDown = (e) => {
399
- let t = this.getRootTriggerForEvent(e);
400
- if (!t || e.key !== "ArrowDown" && e.key !== "ArrowUp" || this.hidden) return;
401
- e.preventDefault(), this.isActive() || this.showPopoverWithSource(t);
402
- let n = this.getEnabledItems();
403
- e.key === "ArrowDown" ? n[0]?.focus() : n[n.length - 1]?.focus();
1114
+ const trigger = this.getRootTriggerForEvent(e);
1115
+ if (!trigger) return;
1116
+ if (e.key !== "ArrowDown" && e.key !== "ArrowUp") return;
1117
+ if (this.hidden) return;
1118
+ e.preventDefault();
1119
+ if (!this.isActive()) this.showPopoverWithSource(trigger);
1120
+ const items = this.getEnabledItems();
1121
+ if (e.key === "ArrowDown") items[0]?.focus();
1122
+ else items[items.length - 1]?.focus();
404
1123
  };
405
1124
  onKeyDown = (e) => {
406
1125
  if (!this.isActive()) return;
407
1126
  if (e.key === "Tab") {
408
- this.closeMenuTree(), this.focusRootMenuTrigger();
1127
+ this.closeMenuTree();
1128
+ this.focusRootMenuTrigger();
409
1129
  return;
410
1130
  }
411
1131
  if (e.key === "Escape") {
412
- e.preventDefault(), this.closeMenuTree(), this.focusRootMenuTrigger();
1132
+ e.preventDefault();
1133
+ this.closeMenuTree();
1134
+ this.focusRootMenuTrigger();
413
1135
  return;
414
1136
  }
415
- let t = this.getEnabledItems(), n = this.getActiveItem(t), r = n ? t.indexOf(n) : -1;
416
- if (r === -1) {
1137
+ const items = this.getEnabledItems();
1138
+ const activeItem = this.getActiveItem(items);
1139
+ const activeIndex = activeItem ? items.indexOf(activeItem) : -1;
1140
+ if (activeIndex === -1) {
417
1141
  if (!this.horizontal && e.key === "ArrowDown" || this.horizontal && e.key === "ArrowRight") {
418
- t[0]?.focus(), e.preventDefault();
1142
+ items[0]?.focus();
1143
+ e.preventDefault();
419
1144
  return;
420
1145
  }
421
1146
  if (!this.horizontal && e.key === "ArrowUp" || this.horizontal && e.key === "ArrowLeft") {
422
- t[t.length - 1]?.focus(), e.preventDefault();
1147
+ items[items.length - 1]?.focus();
1148
+ e.preventDefault();
423
1149
  return;
424
1150
  }
425
1151
  }
426
- let i = n ? this.getSubmenu(n) : null;
427
- if (n && i) {
1152
+ const activeSubmenu = activeItem ? this.getSubmenu(activeItem) : null;
1153
+ if (activeItem && activeSubmenu) {
428
1154
  if (!this.horizontal && e.key === "ArrowRight" || this.horizontal && e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
429
- this.openSubmenu(n), i.getItems()[0]?.focus();
1155
+ this.openSubmenu(activeItem);
1156
+ activeSubmenu.getItems()[0]?.focus();
430
1157
  return;
431
1158
  }
432
1159
  if (this.horizontal && e.key === "ArrowUp") {
433
- this.openSubmenu(n), i.getItems().at(-1)?.focus();
1160
+ this.openSubmenu(activeItem);
1161
+ activeSubmenu.getItems().at(-1)?.focus();
434
1162
  return;
435
1163
  }
436
1164
  }
437
- let a = this.getParentMenuTrigger(), o = a?.closest("ui-menu");
438
- if (o && e.key === (o.horizontal ? "ArrowUp" : "ArrowLeft")) {
439
- this.closeSelfAndDescendants(), a?.focus({ preventScroll: !0 });
1165
+ const parentMenuTrigger = this.getParentMenuTrigger();
1166
+ const parentMenu = parentMenuTrigger?.closest("ui-menu");
1167
+ if (parentMenu && e.key === (parentMenu.horizontal ? "ArrowUp" : "ArrowLeft")) {
1168
+ this.closeSelfAndDescendants();
1169
+ parentMenuTrigger?.focus({ preventScroll: true });
440
1170
  return;
441
1171
  }
442
- let s = F(e.key, {
443
- currentIndex: r,
444
- length: t.length,
1172
+ const nextIndex = getRovingIndexForKey(e.key, {
1173
+ currentIndex: activeIndex,
1174
+ length: items.length,
445
1175
  vertical: !this.horizontal
446
1176
  });
447
- if (s !== void 0) {
448
- t[s]?.focus(), e.preventDefault();
1177
+ if (nextIndex !== void 0) {
1178
+ items[nextIndex]?.focus();
1179
+ e.preventDefault();
449
1180
  return;
450
1181
  }
451
- this.handleTypeahead(e, t, n);
1182
+ this.handleTypeahead(e, items, activeItem);
452
1183
  };
453
1184
  onClick = (e) => {
454
- let t = this.getItemForEvent(e);
455
- if (!t) return;
456
- let n = this.getSubmenu(t);
457
- if (n) {
458
- e.preventDefault(), n.isActive() || (this.openSubmenu(t), n.getItems()[0]?.focus());
1185
+ const item = this.getItemForEvent(e);
1186
+ if (!item) return;
1187
+ const submenu = this.getSubmenu(item);
1188
+ if (submenu) {
1189
+ e.preventDefault();
1190
+ if (!submenu.isActive()) {
1191
+ this.openSubmenu(item);
1192
+ submenu.getItems()[0]?.focus();
1193
+ }
459
1194
  return;
460
1195
  }
461
1196
  this.closeMenuTree();
462
1197
  };
463
1198
  onMouseEnter = (e) => {
464
1199
  if (!this.isActive()) return;
465
- let t = this.getItemForEvent(e);
466
- if (t) {
467
- if (t.focus(), this.getSubmenu(t)) {
468
- this.openSubmenu(t);
469
- return;
470
- }
471
- this.closeSubmenus();
1200
+ const item = this.getItemForEvent(e);
1201
+ if (!item) return;
1202
+ item.focus();
1203
+ if (this.getSubmenu(item)) {
1204
+ this.openSubmenu(item);
1205
+ return;
472
1206
  }
1207
+ this.closeSubmenus();
473
1208
  };
474
1209
  isActive() {
475
- return this.hidden ? !1 : !this.hasAttribute("popover") || this.matches(":popover-open");
1210
+ if (this.hidden) return false;
1211
+ return !this.hasAttribute("popover") || this.matches(":popover-open");
476
1212
  }
477
1213
  syncItems() {
478
- this.getItems().forEach((e) => {
479
- e.getAttribute("tabindex") !== "-1" && e.setAttribute("tabindex", "-1");
1214
+ this.getItems().forEach((item) => {
1215
+ if (item.getAttribute("tabindex") !== "-1") item.setAttribute("tabindex", "-1");
480
1216
  });
481
1217
  }
482
1218
  getItems() {
483
- return Array.from(this.querySelectorAll("[role^=menuitem]")).filter((e) => this.belongsToThisMenu(e));
1219
+ return Array.from(this.querySelectorAll("[role^=menuitem]")).filter((item) => this.belongsToThisMenu(item));
484
1220
  }
485
1221
  getEnabledItems() {
486
- return this.getItems().filter((e) => this.isItemEnabled(e));
1222
+ return this.getItems().filter((item) => this.isItemEnabled(item));
487
1223
  }
488
- isItemEnabled(e) {
489
- return !e.hidden && !e.hasAttribute("disabled") && e.getAttribute("aria-disabled") !== "true";
1224
+ isItemEnabled(item) {
1225
+ return !item.hidden && !item.hasAttribute("disabled") && item.getAttribute("aria-disabled") !== "true";
490
1226
  }
491
- belongsToThisMenu(e) {
492
- return e.closest("ui-menu") === this;
1227
+ belongsToThisMenu(item) {
1228
+ return item.closest("ui-menu") === this;
493
1229
  }
494
- getActiveItem(e) {
495
- let t = P(this).activeElement;
496
- return e.find((e) => e === t);
1230
+ getActiveItem(items) {
1231
+ const activeElement = getLookupRoot(this).activeElement;
1232
+ return items.find((item) => item === activeElement);
497
1233
  }
498
- getItemForEvent(e) {
499
- let t = e.target;
500
- if (!(t instanceof Element)) return null;
501
- let n = t.closest("[role^=menuitem]");
502
- return n && this.belongsToThisMenu(n) && this.isItemEnabled(n) ? n : null;
1234
+ getItemForEvent(event) {
1235
+ const target = event.target;
1236
+ if (!(target instanceof Element)) return null;
1237
+ const item = target.closest("[role^=menuitem]");
1238
+ return item && this.belongsToThisMenu(item) && this.isItemEnabled(item) ? item : null;
503
1239
  }
504
- getRootTriggerForEvent(e) {
505
- for (let t of e.composedPath()) if (t instanceof HTMLElement && !t.closest("ui-menu") && t.getAttribute("popovertarget") === this.id) return t;
1240
+ getRootTriggerForEvent(event) {
1241
+ for (const candidate of event.composedPath()) if (candidate instanceof HTMLElement && !candidate.closest("ui-menu") && candidate.getAttribute("popovertarget") === this.id) return candidate;
506
1242
  return null;
507
1243
  }
508
1244
  getTriggers() {
509
- return this.id ? Array.from(P(this).querySelectorAll(`[popovertarget="${CSS.escape(this.id)}"]`)) : [];
1245
+ if (!this.id) return [];
1246
+ return Array.from(getLookupRoot(this).querySelectorAll(`[popovertarget="${CSS.escape(this.id)}"]`));
510
1247
  }
511
1248
  getParentMenuTrigger() {
512
- return this.getTriggers().find((e) => e.closest("ui-menu")) || null;
1249
+ return this.getTriggers().find((trigger) => trigger.closest("ui-menu")) || null;
513
1250
  }
514
1251
  getParentMenu() {
515
1252
  return this.getParentMenuTrigger()?.closest("ui-menu") || null;
516
1253
  }
517
- getSubmenu(e) {
518
- let t = e.getAttribute("popovertarget");
519
- return t ? P(this).querySelector(`ui-menu#${CSS.escape(t)}`) : null;
1254
+ getSubmenu(item) {
1255
+ const id = item.getAttribute("popovertarget");
1256
+ if (!id) return null;
1257
+ return getLookupRoot(this).querySelector(`ui-menu#${CSS.escape(id)}`);
520
1258
  }
521
- openSubmenu(e) {
522
- let t = this.getSubmenu(e);
523
- t && (this.closeSubmenus(), t.showPopoverWithSource(e));
1259
+ openSubmenu(item) {
1260
+ const submenu = this.getSubmenu(item);
1261
+ if (!submenu) return;
1262
+ this.closeSubmenus();
1263
+ submenu.showPopoverWithSource(item);
524
1264
  }
525
1265
  closeSubmenus() {
526
- this.getItems().forEach((e) => this.getSubmenu(e)?.closeSelfAndDescendants());
1266
+ this.getItems().forEach((item) => this.getSubmenu(item)?.closeSelfAndDescendants());
527
1267
  }
528
1268
  closeSelfAndDescendants() {
529
- this.closeSubmenus(), this.hasAttribute("popover") && this.matches(":popover-open") && this.hidePopover();
1269
+ this.closeSubmenus();
1270
+ if (this.hasAttribute("popover") && this.matches(":popover-open")) this.hidePopover();
530
1271
  }
531
1272
  closeMenuTree() {
532
- this.closeSelfAndDescendants(), this.getParentMenu()?.closeMenuTree();
1273
+ this.closeSelfAndDescendants();
1274
+ this.getParentMenu()?.closeMenuTree();
533
1275
  }
534
1276
  focusRootMenuTrigger() {
535
- this.getRootMenuTrigger()?.focus({ preventScroll: !0 });
1277
+ this.getRootMenuTrigger()?.focus({ preventScroll: true });
536
1278
  }
537
1279
  getRootMenuTrigger() {
538
- let e = this.getParentMenu();
539
- return e ? e.getRootMenuTrigger() : this.getTriggers()[0] || null;
1280
+ const parentMenu = this.getParentMenu();
1281
+ return parentMenu ? parentMenu.getRootMenuTrigger() : this.getTriggers()[0] || null;
540
1282
  }
541
- handleTypeahead(e, t, n) {
542
- if (e.key === " " || e.key.length > 1 || e.ctrlKey || e.metaKey || e.altKey || !t.length) return;
1283
+ handleTypeahead(e, items, activeItem) {
1284
+ if (e.key === " ") return;
1285
+ if (e.key.length > 1 || e.ctrlKey || e.metaKey || e.altKey) return;
1286
+ if (!items.length) return;
543
1287
  e.preventDefault();
544
- let r = this.updateTypeaheadSearch(e.key), i = n ? t.indexOf(n) : -1;
545
- this.findTypeaheadMatch(t, r, i)?.focus();
546
- }
547
- updateTypeaheadSearch(t) {
548
- return this.search += t.toLowerCase(), clearTimeout(this.searchTimeout), this.searchTimeout = window.setTimeout(() => {
1288
+ const search = this.updateTypeaheadSearch(e.key);
1289
+ const startIndex = activeItem ? items.indexOf(activeItem) : -1;
1290
+ this.findTypeaheadMatch(items, search, startIndex)?.focus();
1291
+ }
1292
+ updateTypeaheadSearch(key) {
1293
+ this.search += key.toLowerCase();
1294
+ clearTimeout(this.searchTimeout);
1295
+ this.searchTimeout = window.setTimeout(() => {
549
1296
  this.search = "";
550
- }, e.searchDelay), this.search.length > 1 && this.search.split("").every((e) => e === this.search[0]) ? this.search[0] : this.search;
551
- }
552
- findTypeaheadMatch(e, t, n) {
553
- for (let r = 1; r <= e.length; r += 1) {
554
- let i = e[(n + r + e.length) % e.length];
555
- if (this.getItemLabel(i).startsWith(t)) return i;
1297
+ }, MenuElement.searchDelay);
1298
+ if (this.search.length > 1 && this.search.split("").every((character) => character === this.search[0])) return this.search[0];
1299
+ return this.search;
1300
+ }
1301
+ findTypeaheadMatch(items, search, startIndex) {
1302
+ for (let offset = 1; offset <= items.length; offset += 1) {
1303
+ const item = items[(startIndex + offset + items.length) % items.length];
1304
+ if (this.getItemLabel(item).startsWith(search)) return item;
556
1305
  }
557
1306
  }
558
- getItemLabel(e) {
559
- return (e.getAttribute("aria-label") || e.textContent || "").trim().toLowerCase();
1307
+ getItemLabel(item) {
1308
+ return (item.getAttribute("aria-label") || item.textContent || "").trim().toLowerCase();
560
1309
  }
561
- showPopoverWithSource(e) {
562
- this.showPopover?.({ source: e });
1310
+ showPopoverWithSource(source) {
1311
+ this.showPopover?.({ source });
563
1312
  }
564
- }, L = /* @__PURE__ */ [
1313
+ };
1314
+ /*!
1315
+ * tabbable 6.4.0
1316
+ * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
1317
+ */
1318
+ var candidateSelector = /* #__PURE__ */ [
565
1319
  "input:not([inert]):not([inert] *)",
566
1320
  "select:not([inert]):not([inert] *)",
567
1321
  "textarea:not([inert]):not([inert] *)",
@@ -573,305 +1327,514 @@ var I = class e extends HTMLElement {
573
1327
  "[contenteditable]:not([contenteditable=\"false\"]):not([inert]):not([inert] *)",
574
1328
  "details>summary:first-of-type:not([inert]):not([inert] *)",
575
1329
  "details:not([inert]):not([inert] *)"
576
- ].join(","), R = typeof Element > "u", z = R ? function() {} : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector, B = !R && Element.prototype.getRootNode ? function(e) {
577
- return e?.getRootNode?.call(e);
578
- } : function(e) {
579
- return e?.ownerDocument;
580
- }, V = function(e, t) {
581
- t === void 0 && (t = !0);
582
- var n = e?.getAttribute?.call(e, "inert");
583
- return n === "" || n === "true" || t && e && (typeof e.closest == "function" ? e.closest("[inert]") : V(e.parentNode));
584
- }, H = function(e) {
585
- var t = e?.getAttribute?.call(e, "contenteditable");
586
- return t === "" || t === "true";
587
- }, U = function(e, t, n) {
588
- if (V(e)) return [];
589
- var r = Array.prototype.slice.apply(e.querySelectorAll(L));
590
- return t && z.call(e, L) && r.unshift(e), r = r.filter(n), r;
591
- }, W = function(e, t, n) {
592
- for (var r = [], i = Array.from(e); i.length;) {
593
- var a = i.shift();
594
- if (!V(a, !1)) if (a.tagName === "SLOT") {
595
- var o = a.assignedElements(), s = W(o.length ? o : a.children, !0, n);
596
- n.flatten ? r.push.apply(r, s) : r.push({
597
- scopeParent: a,
598
- candidates: s
1330
+ ].join(",");
1331
+ var NoElement = typeof Element === "undefined";
1332
+ var matches = NoElement ? function() {} : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
1333
+ var getRootNode = !NoElement && Element.prototype.getRootNode ? function(element) {
1334
+ var _element$getRootNode;
1335
+ return element === null || element === void 0 ? void 0 : (_element$getRootNode = element.getRootNode) === null || _element$getRootNode === void 0 ? void 0 : _element$getRootNode.call(element);
1336
+ } : function(element) {
1337
+ return element === null || element === void 0 ? void 0 : element.ownerDocument;
1338
+ };
1339
+ /**
1340
+ * Determines if a node is inert or in an inert ancestor.
1341
+ * @param {Node} [node]
1342
+ * @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to
1343
+ * see if any of them are inert. If false, only `node` itself is considered.
1344
+ * @returns {boolean} True if inert itself or by way of being in an inert ancestor.
1345
+ * False if `node` is falsy.
1346
+ */
1347
+ var _isInert = function isInert(node, lookUp) {
1348
+ var _node$getAttribute;
1349
+ if (lookUp === void 0) lookUp = true;
1350
+ var inertAtt = node === null || node === void 0 ? void 0 : (_node$getAttribute = node.getAttribute) === null || _node$getAttribute === void 0 ? void 0 : _node$getAttribute.call(node, "inert");
1351
+ return inertAtt === "" || inertAtt === "true" || lookUp && node && (typeof node.closest === "function" ? node.closest("[inert]") : _isInert(node.parentNode));
1352
+ };
1353
+ /**
1354
+ * Determines if a node's content is editable.
1355
+ * @param {Element} [node]
1356
+ * @returns True if it's content-editable; false if it's not or `node` is falsy.
1357
+ */
1358
+ var isContentEditable = function isContentEditable(node) {
1359
+ var _node$getAttribute2;
1360
+ var attValue = node === null || node === void 0 ? void 0 : (_node$getAttribute2 = node.getAttribute) === null || _node$getAttribute2 === void 0 ? void 0 : _node$getAttribute2.call(node, "contenteditable");
1361
+ return attValue === "" || attValue === "true";
1362
+ };
1363
+ /**
1364
+ * @param {Element} el container to check in
1365
+ * @param {boolean} includeContainer add container to check
1366
+ * @param {(node: Element) => boolean} filter filter candidates
1367
+ * @returns {Element[]}
1368
+ */
1369
+ var getCandidates = function getCandidates(el, includeContainer, filter) {
1370
+ if (_isInert(el)) return [];
1371
+ var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
1372
+ if (includeContainer && matches.call(el, candidateSelector)) candidates.unshift(el);
1373
+ candidates = candidates.filter(filter);
1374
+ return candidates;
1375
+ };
1376
+ /**
1377
+ * @callback GetShadowRoot
1378
+ * @param {Element} element to check for shadow root
1379
+ * @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available.
1380
+ */
1381
+ /**
1382
+ * @callback ShadowRootFilter
1383
+ * @param {Element} shadowHostNode the element which contains shadow content
1384
+ * @returns {boolean} true if a shadow root could potentially contain valid candidates.
1385
+ */
1386
+ /**
1387
+ * @typedef {Object} CandidateScope
1388
+ * @property {Element} scopeParent contains inner candidates
1389
+ * @property {Element[]} candidates list of candidates found in the scope parent
1390
+ */
1391
+ /**
1392
+ * @typedef {Object} IterativeOptions
1393
+ * @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not;
1394
+ * if a function, implies shadow support is enabled and either returns the shadow root of an element
1395
+ * or a boolean stating if it has an undisclosed shadow root
1396
+ * @property {(node: Element) => boolean} filter filter candidates
1397
+ * @property {boolean} flatten if true then result will flatten any CandidateScope into the returned list
1398
+ * @property {ShadowRootFilter} shadowRootFilter filter shadow roots;
1399
+ */
1400
+ /**
1401
+ * @param {Element[]} elements list of element containers to match candidates from
1402
+ * @param {boolean} includeContainer add container list to check
1403
+ * @param {IterativeOptions} options
1404
+ * @returns {Array.<Element|CandidateScope>}
1405
+ */
1406
+ var _getCandidatesIteratively = function getCandidatesIteratively(elements, includeContainer, options) {
1407
+ var candidates = [];
1408
+ var elementsToCheck = Array.from(elements);
1409
+ while (elementsToCheck.length) {
1410
+ var element = elementsToCheck.shift();
1411
+ if (_isInert(element, false)) continue;
1412
+ if (element.tagName === "SLOT") {
1413
+ var assigned = element.assignedElements();
1414
+ var nestedCandidates = _getCandidatesIteratively(assigned.length ? assigned : element.children, true, options);
1415
+ if (options.flatten) candidates.push.apply(candidates, nestedCandidates);
1416
+ else candidates.push({
1417
+ scopeParent: element,
1418
+ candidates: nestedCandidates
599
1419
  });
600
1420
  } else {
601
- z.call(a, L) && n.filter(a) && (t || !e.includes(a)) && r.push(a);
602
- var c = a.shadowRoot || typeof n.getShadowRoot == "function" && n.getShadowRoot(a), l = !V(c, !1) && (!n.shadowRootFilter || n.shadowRootFilter(a));
603
- if (c && l) {
604
- var u = W(c === !0 ? a.children : c.children, !0, n);
605
- n.flatten ? r.push.apply(r, u) : r.push({
606
- scopeParent: a,
607
- candidates: u
1421
+ if (matches.call(element, candidateSelector) && options.filter(element) && (includeContainer || !elements.includes(element))) candidates.push(element);
1422
+ var shadowRoot = element.shadowRoot || typeof options.getShadowRoot === "function" && options.getShadowRoot(element);
1423
+ var validShadowRoot = !_isInert(shadowRoot, false) && (!options.shadowRootFilter || options.shadowRootFilter(element));
1424
+ if (shadowRoot && validShadowRoot) {
1425
+ var _nestedCandidates = _getCandidatesIteratively(shadowRoot === true ? element.children : shadowRoot.children, true, options);
1426
+ if (options.flatten) candidates.push.apply(candidates, _nestedCandidates);
1427
+ else candidates.push({
1428
+ scopeParent: element,
1429
+ candidates: _nestedCandidates
608
1430
  });
609
- } else i.unshift.apply(i, a.children);
1431
+ } else elementsToCheck.unshift.apply(elementsToCheck, element.children);
610
1432
  }
611
1433
  }
612
- return r;
613
- }, G = function(e) {
614
- return !isNaN(parseInt(e.getAttribute("tabindex"), 10));
615
- }, K = function(e) {
616
- if (!e) throw Error("No node provided");
617
- return e.tabIndex < 0 && (/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName) || H(e)) && !G(e) ? 0 : e.tabIndex;
618
- }, q = function(e, t) {
619
- var n = K(e);
620
- return n < 0 && t && !G(e) ? 0 : n;
621
- }, J = function(e, t) {
622
- return e.tabIndex === t.tabIndex ? e.documentOrder - t.documentOrder : e.tabIndex - t.tabIndex;
623
- }, Y = function(e) {
624
- return e.tagName === "INPUT";
625
- }, ie = function(e) {
626
- return Y(e) && e.type === "hidden";
627
- }, ae = function(e) {
628
- return e.tagName === "DETAILS" && Array.prototype.slice.apply(e.children).some(function(e) {
629
- return e.tagName === "SUMMARY";
1434
+ return candidates;
1435
+ };
1436
+ /**
1437
+ * @private
1438
+ * Determines if the node has an explicitly specified `tabindex` attribute.
1439
+ * @param {HTMLElement} node
1440
+ * @returns {boolean} True if so; false if not.
1441
+ */
1442
+ var hasTabIndex = function hasTabIndex(node) {
1443
+ return !isNaN(parseInt(node.getAttribute("tabindex"), 10));
1444
+ };
1445
+ /**
1446
+ * Determine the tab index of a given node.
1447
+ * @param {HTMLElement} node
1448
+ * @returns {number} Tab order (negative, 0, or positive number).
1449
+ * @throws {Error} If `node` is falsy.
1450
+ */
1451
+ var getTabIndex = function getTabIndex(node) {
1452
+ if (!node) throw new Error("No node provided");
1453
+ if (node.tabIndex < 0) {
1454
+ if ((/^(AUDIO|VIDEO|DETAILS)$/.test(node.tagName) || isContentEditable(node)) && !hasTabIndex(node)) return 0;
1455
+ }
1456
+ return node.tabIndex;
1457
+ };
1458
+ /**
1459
+ * Determine the tab index of a given node __for sort order purposes__.
1460
+ * @param {HTMLElement} node
1461
+ * @param {boolean} [isScope] True for a custom element with shadow root or slot that, by default,
1462
+ * has tabIndex -1, but needs to be sorted by document order in order for its content to be
1463
+ * inserted into the correct sort position.
1464
+ * @returns {number} Tab order (negative, 0, or positive number).
1465
+ */
1466
+ var getSortOrderTabIndex = function getSortOrderTabIndex(node, isScope) {
1467
+ var tabIndex = getTabIndex(node);
1468
+ if (tabIndex < 0 && isScope && !hasTabIndex(node)) return 0;
1469
+ return tabIndex;
1470
+ };
1471
+ var sortOrderedTabbables = function sortOrderedTabbables(a, b) {
1472
+ return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
1473
+ };
1474
+ var isInput = function isInput(node) {
1475
+ return node.tagName === "INPUT";
1476
+ };
1477
+ var isHiddenInput = function isHiddenInput(node) {
1478
+ return isInput(node) && node.type === "hidden";
1479
+ };
1480
+ var isDetailsWithSummary = function isDetailsWithSummary(node) {
1481
+ return node.tagName === "DETAILS" && Array.prototype.slice.apply(node.children).some(function(child) {
1482
+ return child.tagName === "SUMMARY";
630
1483
  });
631
- }, oe = function(e, t) {
632
- for (var n = 0; n < e.length; n++) if (e[n].checked && e[n].form === t) return e[n];
633
- }, se = function(e) {
634
- if (!e.name) return !0;
635
- var t = e.form || B(e), n = function(e) {
636
- return t.querySelectorAll("input[type=\"radio\"][name=\"" + e + "\"]");
637
- }, r;
638
- if (typeof window < "u" && window.CSS !== void 0 && typeof window.CSS.escape == "function") r = n(window.CSS.escape(e.name));
1484
+ };
1485
+ var getCheckedRadio = function getCheckedRadio(nodes, form) {
1486
+ for (var i = 0; i < nodes.length; i++) if (nodes[i].checked && nodes[i].form === form) return nodes[i];
1487
+ };
1488
+ var isTabbableRadio = function isTabbableRadio(node) {
1489
+ if (!node.name) return true;
1490
+ var radioScope = node.form || getRootNode(node);
1491
+ var queryRadios = function queryRadios(name) {
1492
+ return radioScope.querySelectorAll("input[type=\"radio\"][name=\"" + name + "\"]");
1493
+ };
1494
+ var radioSet;
1495
+ if (typeof window !== "undefined" && typeof window.CSS !== "undefined" && typeof window.CSS.escape === "function") radioSet = queryRadios(window.CSS.escape(node.name));
639
1496
  else try {
640
- r = n(e.name);
641
- } catch (e) {
642
- return console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s", e.message), !1;
643
- }
644
- var i = oe(r, e.form);
645
- return !i || i === e;
646
- }, ce = function(e) {
647
- return Y(e) && e.type === "radio";
648
- }, le = function(e) {
649
- return ce(e) && !se(e);
650
- }, ue = function(e) {
651
- var t = e && B(e), n = t?.host, r = !1;
652
- if (t && t !== e) {
653
- var i, a, o;
654
- for (r = !!((i = n) != null && (a = i.ownerDocument) != null && a.contains(n) || e != null && (o = e.ownerDocument) != null && o.contains(e)); !r && n;) {
655
- var s, c;
656
- t = B(n), n = t?.host, r = !!((s = n) != null && (c = s.ownerDocument) != null && c.contains(n));
1497
+ radioSet = queryRadios(node.name);
1498
+ } catch (err) {
1499
+ console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s", err.message);
1500
+ return false;
1501
+ }
1502
+ var checked = getCheckedRadio(radioSet, node.form);
1503
+ return !checked || checked === node;
1504
+ };
1505
+ var isRadio = function isRadio(node) {
1506
+ return isInput(node) && node.type === "radio";
1507
+ };
1508
+ var isNonTabbableRadio = function isNonTabbableRadio(node) {
1509
+ return isRadio(node) && !isTabbableRadio(node);
1510
+ };
1511
+ var isNodeAttached = function isNodeAttached(node) {
1512
+ var _nodeRoot;
1513
+ var nodeRoot = node && getRootNode(node);
1514
+ var nodeRootHost = (_nodeRoot = nodeRoot) === null || _nodeRoot === void 0 ? void 0 : _nodeRoot.host;
1515
+ var attached = false;
1516
+ if (nodeRoot && nodeRoot !== node) {
1517
+ var _nodeRootHost, _nodeRootHost$ownerDo, _node$ownerDocument;
1518
+ attached = !!((_nodeRootHost = nodeRootHost) !== null && _nodeRootHost !== void 0 && (_nodeRootHost$ownerDo = _nodeRootHost.ownerDocument) !== null && _nodeRootHost$ownerDo !== void 0 && _nodeRootHost$ownerDo.contains(nodeRootHost) || node !== null && node !== void 0 && (_node$ownerDocument = node.ownerDocument) !== null && _node$ownerDocument !== void 0 && _node$ownerDocument.contains(node));
1519
+ while (!attached && nodeRootHost) {
1520
+ var _nodeRoot2, _nodeRootHost2, _nodeRootHost2$ownerD;
1521
+ nodeRoot = getRootNode(nodeRootHost);
1522
+ nodeRootHost = (_nodeRoot2 = nodeRoot) === null || _nodeRoot2 === void 0 ? void 0 : _nodeRoot2.host;
1523
+ attached = !!((_nodeRootHost2 = nodeRootHost) !== null && _nodeRootHost2 !== void 0 && (_nodeRootHost2$ownerD = _nodeRootHost2.ownerDocument) !== null && _nodeRootHost2$ownerD !== void 0 && _nodeRootHost2$ownerD.contains(nodeRootHost));
657
1524
  }
658
1525
  }
659
- return r;
660
- }, X = function(e) {
661
- var t = e.getBoundingClientRect(), n = t.width, r = t.height;
662
- return n === 0 && r === 0;
663
- }, de = function(e, t) {
664
- var n = t.displayCheck, r = t.getShadowRoot;
665
- if (n === "full-native" && "checkVisibility" in e) return !e.checkVisibility({
666
- checkOpacity: !1,
667
- opacityProperty: !1,
668
- contentVisibilityAuto: !0,
669
- visibilityProperty: !0,
670
- checkVisibilityCSS: !0
671
- });
672
- if (getComputedStyle(e).visibility === "hidden") return !0;
673
- var i = z.call(e, "details>summary:first-of-type") ? e.parentElement : e;
674
- if (z.call(i, "details:not([open]) *")) return !0;
675
- if (!n || n === "full" || n === "full-native" || n === "legacy-full") {
676
- if (typeof r == "function") {
677
- for (var a = e; e;) {
678
- var o = e.parentElement, s = B(e);
679
- if (o && !o.shadowRoot && r(o) === !0) return X(e);
680
- e = e.assignedSlot ? e.assignedSlot : !o && s !== e.ownerDocument ? s.host : o;
1526
+ return attached;
1527
+ };
1528
+ var isZeroArea = function isZeroArea(node) {
1529
+ var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height;
1530
+ return width === 0 && height === 0;
1531
+ };
1532
+ var isHidden = function isHidden(node, _ref) {
1533
+ var displayCheck = _ref.displayCheck, getShadowRoot = _ref.getShadowRoot;
1534
+ if (displayCheck === "full-native") {
1535
+ if ("checkVisibility" in node) return !node.checkVisibility({
1536
+ checkOpacity: false,
1537
+ opacityProperty: false,
1538
+ contentVisibilityAuto: true,
1539
+ visibilityProperty: true,
1540
+ checkVisibilityCSS: true
1541
+ });
1542
+ }
1543
+ if (getComputedStyle(node).visibility === "hidden") return true;
1544
+ var nodeUnderDetails = matches.call(node, "details>summary:first-of-type") ? node.parentElement : node;
1545
+ if (matches.call(nodeUnderDetails, "details:not([open]) *")) return true;
1546
+ if (!displayCheck || displayCheck === "full" || displayCheck === "full-native" || displayCheck === "legacy-full") {
1547
+ if (typeof getShadowRoot === "function") {
1548
+ var originalNode = node;
1549
+ while (node) {
1550
+ var parentElement = node.parentElement;
1551
+ var rootNode = getRootNode(node);
1552
+ if (parentElement && !parentElement.shadowRoot && getShadowRoot(parentElement) === true) return isZeroArea(node);
1553
+ else if (node.assignedSlot) node = node.assignedSlot;
1554
+ else if (!parentElement && rootNode !== node.ownerDocument) node = rootNode.host;
1555
+ else node = parentElement;
681
1556
  }
682
- e = a;
683
- }
684
- if (ue(e)) return !e.getClientRects().length;
685
- if (n !== "legacy-full") return !0;
686
- } else if (n === "non-zero-area") return X(e);
687
- return !1;
688
- }, fe = function(e) {
689
- if (/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName)) for (var t = e.parentElement; t;) {
690
- if (t.tagName === "FIELDSET" && t.disabled) {
691
- for (var n = 0; n < t.children.length; n++) {
692
- var r = t.children.item(n);
693
- if (r.tagName === "LEGEND") return z.call(t, "fieldset[disabled] *") ? !0 : !r.contains(e);
1557
+ node = originalNode;
1558
+ }
1559
+ if (isNodeAttached(node)) return !node.getClientRects().length;
1560
+ if (displayCheck !== "legacy-full") return true;
1561
+ } else if (displayCheck === "non-zero-area") return isZeroArea(node);
1562
+ return false;
1563
+ };
1564
+ var isDisabledFromFieldset = function isDisabledFromFieldset(node) {
1565
+ if (/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(node.tagName)) {
1566
+ var parentNode = node.parentElement;
1567
+ while (parentNode) {
1568
+ if (parentNode.tagName === "FIELDSET" && parentNode.disabled) {
1569
+ for (var i = 0; i < parentNode.children.length; i++) {
1570
+ var child = parentNode.children.item(i);
1571
+ if (child.tagName === "LEGEND") return matches.call(parentNode, "fieldset[disabled] *") ? true : !child.contains(node);
1572
+ }
1573
+ return true;
694
1574
  }
695
- return !0;
696
- }
697
- t = t.parentElement;
698
- }
699
- return !1;
700
- }, Z = function(e, t) {
701
- return !(t.disabled || ie(t) || de(t, e) || ae(t) || fe(t));
702
- }, Q = function(e, t) {
703
- return !(le(t) || K(t) < 0 || !Z(e, t));
704
- }, pe = function(e) {
705
- var t = parseInt(e.getAttribute("tabindex"), 10);
706
- return !!(isNaN(t) || t >= 0);
707
- }, $ = function(e) {
708
- var t = [], n = [];
709
- return e.forEach(function(e, r) {
710
- var i = !!e.scopeParent, a = i ? e.scopeParent : e, o = q(a, i), s = i ? $(e.candidates) : a;
711
- o === 0 ? i ? t.push.apply(t, s) : t.push(a) : n.push({
712
- documentOrder: r,
713
- tabIndex: o,
714
- item: e,
715
- isScope: i,
716
- content: s
1575
+ parentNode = parentNode.parentElement;
1576
+ }
1577
+ }
1578
+ return false;
1579
+ };
1580
+ var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable(options, node) {
1581
+ if (node.disabled || isHiddenInput(node) || isHidden(node, options) || isDetailsWithSummary(node) || isDisabledFromFieldset(node)) return false;
1582
+ return true;
1583
+ };
1584
+ var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable(options, node) {
1585
+ if (isNonTabbableRadio(node) || getTabIndex(node) < 0 || !isNodeMatchingSelectorFocusable(options, node)) return false;
1586
+ return true;
1587
+ };
1588
+ var isShadowRootTabbable = function isShadowRootTabbable(shadowHostNode) {
1589
+ var tabIndex = parseInt(shadowHostNode.getAttribute("tabindex"), 10);
1590
+ if (isNaN(tabIndex) || tabIndex >= 0) return true;
1591
+ return false;
1592
+ };
1593
+ /**
1594
+ * @param {Array.<Element|CandidateScope>} candidates
1595
+ * @returns Element[]
1596
+ */
1597
+ var _sortByOrder = function sortByOrder(candidates) {
1598
+ var regularTabbables = [];
1599
+ var orderedTabbables = [];
1600
+ candidates.forEach(function(item, i) {
1601
+ var isScope = !!item.scopeParent;
1602
+ var element = isScope ? item.scopeParent : item;
1603
+ var candidateTabindex = getSortOrderTabIndex(element, isScope);
1604
+ var elements = isScope ? _sortByOrder(item.candidates) : element;
1605
+ if (candidateTabindex === 0) isScope ? regularTabbables.push.apply(regularTabbables, elements) : regularTabbables.push(element);
1606
+ else orderedTabbables.push({
1607
+ documentOrder: i,
1608
+ tabIndex: candidateTabindex,
1609
+ item,
1610
+ isScope,
1611
+ content: elements
717
1612
  });
718
- }), n.sort(J).reduce(function(e, t) {
719
- return t.isScope ? e.push.apply(e, t.content) : e.push(t.content), e;
720
- }, []).concat(t);
721
- }, me = function(e, t) {
722
- return t ||= {}, $(t.getShadowRoot ? W([e], t.includeContainer, {
723
- filter: Q.bind(null, t),
724
- flatten: !1,
725
- getShadowRoot: t.getShadowRoot,
726
- shadowRootFilter: pe
727
- }) : U(e, t.includeContainer, Q.bind(null, t)));
728
- }, he = function(e, t) {
729
- return t ||= {}, t.getShadowRoot ? W([e], t.includeContainer, {
730
- filter: Z.bind(null, t),
731
- flatten: !0,
732
- getShadowRoot: t.getShadowRoot
733
- }) : U(e, t.includeContainer, Z.bind(null, t));
734
- }, ge = 0, _e = class extends HTMLElement {
735
- idPrefix = "tabs" + ++ge;
1613
+ });
1614
+ return orderedTabbables.sort(sortOrderedTabbables).reduce(function(acc, sortable) {
1615
+ sortable.isScope ? acc.push.apply(acc, sortable.content) : acc.push(sortable.content);
1616
+ return acc;
1617
+ }, []).concat(regularTabbables);
1618
+ };
1619
+ var tabbable = function tabbable(container, options) {
1620
+ options = options || {};
1621
+ var candidates;
1622
+ if (options.getShadowRoot) candidates = _getCandidatesIteratively([container], options.includeContainer, {
1623
+ filter: isNodeMatchingSelectorTabbable.bind(null, options),
1624
+ flatten: false,
1625
+ getShadowRoot: options.getShadowRoot,
1626
+ shadowRootFilter: isShadowRootTabbable
1627
+ });
1628
+ else candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
1629
+ return _sortByOrder(candidates);
1630
+ };
1631
+ var focusable = function focusable(container, options) {
1632
+ options = options || {};
1633
+ var candidates;
1634
+ if (options.getShadowRoot) candidates = _getCandidatesIteratively([container], options.includeContainer, {
1635
+ filter: isNodeMatchingSelectorFocusable.bind(null, options),
1636
+ flatten: true,
1637
+ getShadowRoot: options.getShadowRoot
1638
+ });
1639
+ else candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
1640
+ return candidates;
1641
+ };
1642
+ //#endregion
1643
+ //#region src/tabs/tabs.ts
1644
+ let idCounter = 0;
1645
+ var TabsElement = class extends HTMLElement {
1646
+ idPrefix = "tabs" + ++idCounter;
736
1647
  structureSync;
737
1648
  managedPanelTabindex = /* @__PURE__ */ new WeakSet();
738
1649
  connectedCallback() {
739
- this.addEventListener("keydown", this.onKeyDown), this.addEventListener("click", this.onClick), this.structureSync ||= N(this, {
740
- subtree: !0,
741
- childList: !0,
742
- attributes: !0,
1650
+ this.addEventListener("keydown", this.onKeyDown);
1651
+ this.addEventListener("click", this.onClick);
1652
+ if (!this.structureSync) this.structureSync = createQueuedElementSync(this, {
1653
+ subtree: true,
1654
+ childList: true,
1655
+ attributes: true,
743
1656
  attributeFilter: ["role", "aria-selected"]
744
- }, () => this.syncStructure()), this.structureSync.observe(), this.structureSync.queue();
1657
+ }, () => this.syncStructure());
1658
+ this.structureSync.observe();
1659
+ this.structureSync.queue();
745
1660
  }
746
1661
  disconnectedCallback() {
747
- this.removeEventListener("keydown", this.onKeyDown), this.removeEventListener("click", this.onClick), this.structureSync?.disconnect();
1662
+ this.removeEventListener("keydown", this.onKeyDown);
1663
+ this.removeEventListener("click", this.onClick);
1664
+ this.structureSync?.disconnect();
748
1665
  }
749
- selectTab(e, t = {}) {
750
- return this.applySelection(this.tabPairs(), e, t);
1666
+ selectTab(index, options = {}) {
1667
+ return this.applySelection(this.tabPairs(), index, options);
751
1668
  }
752
1669
  onKeyDown = (e) => {
753
- let t = this.tabPairs();
754
- if (!t.length) return;
755
- let n = F(e.key, {
756
- currentIndex: this.getEventTabIndex(e.target, t),
757
- length: t.length,
1670
+ const pairs = this.tabPairs();
1671
+ if (!pairs.length) return;
1672
+ const nextIndex = getRovingIndexForKey(e.key, {
1673
+ currentIndex: this.getEventTabIndex(e.target, pairs),
1674
+ length: pairs.length,
758
1675
  vertical: this.vertical
759
1676
  });
760
- n !== void 0 && (this.applySelection(t, n, { focus: !0 }), e.stopPropagation(), e.preventDefault());
1677
+ if (nextIndex !== void 0) {
1678
+ this.applySelection(pairs, nextIndex, { focus: true });
1679
+ e.stopPropagation();
1680
+ e.preventDefault();
1681
+ }
761
1682
  };
762
1683
  onClick = (e) => {
763
- let t = this.tabPairs();
764
- this.applySelection(t, this.getEventTabIndex(e.target, t), { focus: !0 });
1684
+ const pairs = this.tabPairs();
1685
+ this.applySelection(pairs, this.getEventTabIndex(e.target, pairs), { focus: true });
765
1686
  };
766
1687
  syncStructure() {
767
- let e = this.tabPairs();
768
- e.length && this.applySelection(e, this.getSelectedIndex(e, 0), { emit: !1 });
1688
+ const pairs = this.tabPairs();
1689
+ if (!pairs.length) return;
1690
+ this.applySelection(pairs, this.getSelectedIndex(pairs, 0), { emit: false });
769
1691
  }
770
1692
  get vertical() {
771
1693
  return this.tablist?.getAttribute("aria-orientation") === "vertical";
772
1694
  }
773
1695
  get tablist() {
774
- return Array.from(this.querySelectorAll("[role=tablist]")).find((e) => e.closest("ui-tabs") === this);
1696
+ return Array.from(this.querySelectorAll("[role=tablist]")).find((el) => el.closest("ui-tabs") === this);
775
1697
  }
776
1698
  tabPairs() {
777
- let e = this.tablist;
778
- if (!e) return [];
779
- let t = Array.from(e.querySelectorAll("[role=tab]")), n = Array.from(this.querySelectorAll("[role=tabpanel]")).filter((e) => e.closest("ui-tabs") === this);
780
- t.forEach((e, t) => {
781
- e.id ||= this.idPrefix + "_tab_" + t;
782
- }), n.forEach((e, t) => {
783
- e.id ||= this.idPrefix + "_panel_" + t;
1699
+ const tablist = this.tablist;
1700
+ if (!tablist) return [];
1701
+ const tabs = Array.from(tablist.querySelectorAll("[role=tab]"));
1702
+ const panels = Array.from(this.querySelectorAll("[role=tabpanel]")).filter((el) => el.closest("ui-tabs") === this);
1703
+ tabs.forEach((tab, index) => {
1704
+ if (!tab.id) tab.id = this.idPrefix + "_tab_" + index;
784
1705
  });
785
- let r = t.slice(0, Math.min(t.length, n.length)).map((e, t) => ({
786
- tab: e,
787
- panel: n[t]
1706
+ panels.forEach((panel, index) => {
1707
+ if (!panel.id) panel.id = this.idPrefix + "_panel_" + index;
1708
+ });
1709
+ const pairs = tabs.slice(0, Math.min(tabs.length, panels.length)).map((tab, index) => ({
1710
+ tab,
1711
+ panel: panels[index]
788
1712
  }));
789
- return r.forEach(({ tab: e, panel: t }) => {
790
- e.setAttribute("aria-controls", t.id), t.setAttribute("aria-labelledby", e.id);
791
- }), r;
792
- }
793
- getSelectedIndex(e, t = -1) {
794
- let n = e.findIndex(({ tab: e }) => e.getAttribute("aria-selected") === "true");
795
- return n === -1 ? t : n;
796
- }
797
- getEventTabIndex(e, t) {
798
- if (!(e instanceof Element)) return -1;
799
- let n = e.closest("[role=tab]");
800
- return n ? t.findIndex((e) => e.tab === n) : -1;
801
- }
802
- applySelection(e, t, n = {}) {
803
- let { focus: r = !1, emit: i = !0 } = n;
804
- if (t < 0 || t >= e.length) return !1;
805
- let a = this.getSelectedIndex(e);
806
- return e.forEach(({ tab: e, panel: n }, i) => {
807
- let a = i === t;
808
- e.getAttribute("aria-selected") !== String(a) && e.setAttribute("aria-selected", String(a)), a ? (e.removeAttribute("tabindex"), n.hidden = !1, r && e.focus()) : (e.setAttribute("tabindex", "-1"), n.hidden = !0), this.syncPanelTabindex(n, a);
809
- }), i && a !== t && this.dispatchEvent(new Event("change")), a !== t;
810
- }
811
- syncPanelTabindex(e, t) {
812
- let n = me(e).filter((t) => t !== e);
813
- if (t && !this.hasAuthorManagedTabindex(e) && n.length === 0) {
814
- e.setAttribute("tabindex", "0"), this.managedPanelTabindex.add(e);
1713
+ pairs.forEach(({ tab, panel }) => {
1714
+ tab.setAttribute("aria-controls", panel.id);
1715
+ panel.setAttribute("aria-labelledby", tab.id);
1716
+ });
1717
+ return pairs;
1718
+ }
1719
+ getSelectedIndex(pairs, fallback = -1) {
1720
+ const index = pairs.findIndex(({ tab }) => tab.getAttribute("aria-selected") === "true");
1721
+ return index === -1 ? fallback : index;
1722
+ }
1723
+ getEventTabIndex(target, pairs) {
1724
+ if (!(target instanceof Element)) return -1;
1725
+ const tab = target.closest("[role=tab]");
1726
+ return tab ? pairs.findIndex((pair) => pair.tab === tab) : -1;
1727
+ }
1728
+ applySelection(pairs, index, options = {}) {
1729
+ const { focus = false, emit = true } = options;
1730
+ if (index < 0 || index >= pairs.length) return false;
1731
+ const previousIndex = this.getSelectedIndex(pairs);
1732
+ pairs.forEach(({ tab, panel }, i) => {
1733
+ const selected = i === index;
1734
+ if (tab.getAttribute("aria-selected") !== String(selected)) tab.setAttribute("aria-selected", String(selected));
1735
+ if (selected) {
1736
+ tab.removeAttribute("tabindex");
1737
+ panel.hidden = false;
1738
+ if (focus) tab.focus();
1739
+ } else {
1740
+ tab.setAttribute("tabindex", "-1");
1741
+ panel.hidden = true;
1742
+ }
1743
+ this.syncPanelTabindex(panel, selected);
1744
+ });
1745
+ if (emit && previousIndex !== index) this.dispatchEvent(new Event("change"));
1746
+ return previousIndex !== index;
1747
+ }
1748
+ syncPanelTabindex(panel, selected) {
1749
+ const tabbableDescendants = tabbable(panel).filter((el) => el !== panel);
1750
+ if (selected && !this.hasAuthorManagedTabindex(panel) && tabbableDescendants.length === 0) {
1751
+ panel.setAttribute("tabindex", "0");
1752
+ this.managedPanelTabindex.add(panel);
815
1753
  return;
816
1754
  }
817
- this.managedPanelTabindex.has(e) && (e.removeAttribute("tabindex"), this.managedPanelTabindex.delete(e));
1755
+ if (this.managedPanelTabindex.has(panel)) {
1756
+ panel.removeAttribute("tabindex");
1757
+ this.managedPanelTabindex.delete(panel);
1758
+ }
818
1759
  }
819
- hasAuthorManagedTabindex(e) {
820
- return e.hasAttribute("tabindex") && !this.managedPanelTabindex.has(e);
1760
+ hasAuthorManagedTabindex(panel) {
1761
+ return panel.hasAttribute("tabindex") && !this.managedPanelTabindex.has(panel);
821
1762
  }
822
- }, ve = class extends HTMLElement {
1763
+ };
1764
+ //#endregion
1765
+ //#region src/toolbar/toolbar.ts
1766
+ var ToolbarElement = class extends HTMLElement {
823
1767
  structureSync;
824
1768
  connectedCallback() {
825
- this.hasAttribute("role") || this.setAttribute("role", "toolbar"), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.addEventListener("focus", this.onFocus), this.addEventListener("keydown", this.onKeyDown), this.structureSync ||= N(this, {
826
- subtree: !0,
827
- childList: !0,
828
- attributes: !0,
1769
+ if (!this.hasAttribute("role")) this.setAttribute("role", "toolbar");
1770
+ if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "0");
1771
+ this.addEventListener("focus", this.onFocus);
1772
+ this.addEventListener("keydown", this.onKeyDown);
1773
+ if (!this.structureSync) this.structureSync = createQueuedElementSync(this, {
1774
+ subtree: true,
1775
+ childList: true,
1776
+ attributes: true,
829
1777
  attributeFilter: [
830
1778
  "disabled",
831
1779
  "hidden",
832
1780
  "aria-disabled"
833
1781
  ]
834
- }, () => this.syncControls()), this.structureSync.observe(), this.structureSync.queue();
1782
+ }, () => this.syncControls());
1783
+ this.structureSync.observe();
1784
+ this.structureSync.queue();
835
1785
  }
836
1786
  disconnectedCallback() {
837
- this.removeEventListener("focus", this.onFocus), this.removeEventListener("keydown", this.onKeyDown), this.structureSync?.disconnect();
838
- }
839
- onFocus = (e) => {
840
- e.target === this && (this.removeAttribute("tabindex"), this.syncControls()?.focus());
1787
+ this.removeEventListener("focus", this.onFocus);
1788
+ this.removeEventListener("keydown", this.onKeyDown);
1789
+ this.structureSync?.disconnect();
1790
+ }
1791
+ onFocus = (event) => {
1792
+ if (event.target !== this) return;
1793
+ this.removeAttribute("tabindex");
1794
+ this.syncControls()?.focus();
841
1795
  };
842
1796
  onKeyDown = (e) => {
843
- let t = this.controls, n = t.indexOf(e.target);
844
- if (n === -1) return;
845
- let r = F(e.key, {
846
- currentIndex: n,
847
- length: t.length,
1797
+ const controls = this.controls;
1798
+ const index = controls.indexOf(e.target);
1799
+ if (index === -1) return;
1800
+ const nextIndex = getRovingIndexForKey(e.key, {
1801
+ currentIndex: index,
1802
+ length: controls.length,
848
1803
  vertical: this.vertical
849
1804
  });
850
- if (r === void 0) return;
851
- let i = t[r];
852
- this.syncCurrentControl(t, i), i?.focus(), e.preventDefault();
1805
+ if (nextIndex === void 0) return;
1806
+ const current = controls[nextIndex];
1807
+ this.syncCurrentControl(controls, current);
1808
+ current?.focus();
1809
+ e.preventDefault();
853
1810
  };
854
1811
  syncControls() {
855
- let e = this.controls;
856
- if (!e.length) {
1812
+ const controls = this.controls;
1813
+ if (!controls.length) {
857
1814
  this.setAttribute("tabindex", "0");
858
1815
  return;
859
1816
  }
860
- let t = P(this).activeElement, n = this.hasAttribute("tabindex") ? e[0] : e.find((e) => e === t) || e.find((e) => e.getAttribute("tabindex") === "0") || e[0];
861
- return this.syncCurrentControl(e, n), n;
862
- }
863
- syncCurrentControl(e, t) {
864
- e.forEach((e) => {
865
- e.setAttribute("tabindex", e === t ? "0" : "-1");
1817
+ const activeElement = getLookupRoot(this).activeElement;
1818
+ const current = this.hasAttribute("tabindex") ? controls[0] : controls.find((control) => control === activeElement) || controls.find((control) => control.getAttribute("tabindex") === "0") || controls[0];
1819
+ this.syncCurrentControl(controls, current);
1820
+ return current;
1821
+ }
1822
+ syncCurrentControl(controls, current) {
1823
+ controls.forEach((control) => {
1824
+ control.setAttribute("tabindex", control === current ? "0" : "-1");
866
1825
  });
867
1826
  }
868
1827
  get vertical() {
869
1828
  return this.getAttribute("aria-orientation") === "vertical";
870
1829
  }
871
1830
  get controls() {
872
- return he(this);
1831
+ return focusable(this);
873
1832
  }
874
- }, ye = 0, be = class e extends HTMLElement {
1833
+ };
1834
+ //#endregion
1835
+ //#region src/tooltip/tooltip.ts
1836
+ let tooltipIdCounter = 0;
1837
+ var TooltipElement = class TooltipElement extends HTMLElement {
875
1838
  static delay = 100;
876
1839
  static observedAttributes = [
877
1840
  "disabled",
@@ -880,124 +1843,182 @@ var I = class e extends HTMLElement {
880
1843
  ];
881
1844
  owner;
882
1845
  timeout;
883
- sync = M(this, () => this.syncOwner());
1846
+ sync = createQueuedSync(this, () => this.syncOwner());
884
1847
  ownerObserver;
885
1848
  siblingObserver;
886
1849
  managedDescription;
887
1850
  connectedCallback() {
888
- this.hasAttribute("popover") || this.setAttribute("popover", "hint"), this.hasAttribute("role") || this.setAttribute("role", "tooltip"), this.ensureTooltipId(), this.addEventListener("toggle", this.onToggle), this.addEventListener("pointerenter", this.onTooltipPointerEnter), this.addEventListener("pointerleave", this.onInteractivePointerLeave), this.syncOwner();
1851
+ if (!this.hasAttribute("popover")) this.setAttribute("popover", "hint");
1852
+ if (!this.hasAttribute("role")) this.setAttribute("role", "tooltip");
1853
+ this.ensureTooltipId();
1854
+ this.addEventListener("toggle", this.onToggle);
1855
+ this.addEventListener("pointerenter", this.onTooltipPointerEnter);
1856
+ this.addEventListener("pointerleave", this.onInteractivePointerLeave);
1857
+ this.syncOwner();
889
1858
  }
890
1859
  disconnectedCallback() {
891
- this.removeEventListener("toggle", this.onToggle), this.removeEventListener("pointerenter", this.onTooltipPointerEnter), this.removeEventListener("pointerleave", this.onInteractivePointerLeave), this.ownerDocument.removeEventListener("keydown", this.onDocumentKeyDown), this.siblingObserver?.disconnect(), this.sync.disconnect(), this.setOwner(void 0), clearTimeout(this.timeout);
1860
+ this.removeEventListener("toggle", this.onToggle);
1861
+ this.removeEventListener("pointerenter", this.onTooltipPointerEnter);
1862
+ this.removeEventListener("pointerleave", this.onInteractivePointerLeave);
1863
+ this.ownerDocument.removeEventListener("keydown", this.onDocumentKeyDown);
1864
+ this.siblingObserver?.disconnect();
1865
+ this.sync.disconnect();
1866
+ this.setOwner(void 0);
1867
+ clearTimeout(this.timeout);
892
1868
  }
893
- attributeChangedCallback(e, t, n) {
894
- !this.isConnected || t === n || (e === "id" && !n && this.ensureTooltipId(), this.syncOwner());
1869
+ attributeChangedCallback(name, oldValue, newValue) {
1870
+ if (!this.isConnected || oldValue === newValue) return;
1871
+ if (name === "id" && !newValue) this.ensureTooltipId();
1872
+ this.syncOwner();
895
1873
  }
896
1874
  get disabled() {
897
1875
  return this.hasAttribute("disabled");
898
1876
  }
899
- set disabled(e) {
900
- e ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
1877
+ set disabled(val) {
1878
+ if (val) this.setAttribute("disabled", "");
1879
+ else this.removeAttribute("disabled");
901
1880
  }
902
- show(e = this.resolveOwner()) {
903
- clearTimeout(this.timeout), this.syncOwner(e);
904
- let t = this.owner;
905
- !t || this.matches(":popover-open") || this.showPopover?.({ source: t });
1881
+ show(owner = this.resolveOwner()) {
1882
+ clearTimeout(this.timeout);
1883
+ this.syncOwner(owner);
1884
+ const resolvedOwner = this.owner;
1885
+ if (!resolvedOwner || this.matches(":popover-open")) return;
1886
+ this.showPopover?.({ source: resolvedOwner });
906
1887
  }
907
1888
  hide() {
908
- clearTimeout(this.timeout), this.matches(":popover-open") && this.hidePopover();
1889
+ clearTimeout(this.timeout);
1890
+ if (this.matches(":popover-open")) this.hidePopover();
909
1891
  }
910
1892
  onToggle = (e) => {
911
- if (e.target === this) {
912
- if (e.newState === "open") {
913
- this.ownerDocument.addEventListener("keydown", this.onDocumentKeyDown);
914
- return;
915
- }
916
- this.ownerDocument.removeEventListener("keydown", this.onDocumentKeyDown);
1893
+ if (e.target !== this) return;
1894
+ if (e.newState === "open") {
1895
+ this.ownerDocument.addEventListener("keydown", this.onDocumentKeyDown);
1896
+ return;
917
1897
  }
1898
+ this.ownerDocument.removeEventListener("keydown", this.onDocumentKeyDown);
918
1899
  };
919
1900
  onDocumentKeyDown = (e) => {
920
- e.key === "Escape" && this.hide();
1901
+ if (e.key === "Escape") this.hide();
921
1902
  };
922
- syncOwner(e = this.resolveOwner()) {
923
- if (this.siblingObserver ??= new MutationObserver(this.sync.queue), this.siblingObserver.disconnect(), !this.hasAttribute("for") && this.parentElement && this.siblingObserver.observe(this.parentElement, { childList: !0 }), !e) {
924
- this.hide(), this.setOwner(void 0);
1903
+ syncOwner(owner = this.resolveOwner()) {
1904
+ this.siblingObserver ??= new MutationObserver(this.sync.queue);
1905
+ this.siblingObserver.disconnect();
1906
+ if (!this.hasAttribute("for") && this.parentElement) this.siblingObserver.observe(this.parentElement, { childList: true });
1907
+ if (!owner) {
1908
+ this.hide();
1909
+ this.setOwner(void 0);
925
1910
  return;
926
1911
  }
927
- this.owner && this.owner !== e && this.matches(":popover-open") && this.hide(), this.setOwner(e);
1912
+ if (this.owner && this.owner !== owner && this.matches(":popover-open")) this.hide();
1913
+ this.setOwner(owner);
928
1914
  }
929
- resolveOwner(e) {
930
- let t = e ?? (this.hasAttribute("for") ? this.resolveExplicitOwner() : this.previousElementSibling instanceof HTMLElement ? this.previousElementSibling : void 0);
931
- if (!(this.disabled || !t || !t.isConnected || t === this || this.isOwnerDisabled(t))) return t;
1915
+ resolveOwner(owner) {
1916
+ const candidate = owner ?? (this.hasAttribute("for") ? this.resolveExplicitOwner() : this.previousElementSibling instanceof HTMLElement ? this.previousElementSibling : void 0);
1917
+ if (this.disabled || !candidate || !candidate.isConnected || candidate === this || this.isOwnerDisabled(candidate)) return;
1918
+ return candidate;
932
1919
  }
933
1920
  resolveExplicitOwner() {
934
- let e = this.getAttribute("for");
935
- if (!e) return;
936
- let t = this.getRootNode(), n = t instanceof ShadowRoot && t.querySelector(`#${CSS.escape(e)}`) || this.ownerDocument.getElementById(e);
937
- return n instanceof HTMLElement ? n : void 0;
938
- }
939
- setOwner(e) {
940
- let t = this.owner !== e;
941
- t && this.owner && (this.owner.removeEventListener("focusin", this.onOwnerFocusIn), this.owner.removeEventListener("focusout", this.onOwnerFocusOut), this.owner.removeEventListener("pointerenter", this.onOwnerPointerEnter), this.owner.removeEventListener("pointerleave", this.onInteractivePointerLeave), this.owner.removeEventListener("click", this.onOwnerClick)), this.owner = e, this.updateManagedDescription(e), this.ownerObserver?.disconnect(), e && (this.ownerObserver ??= new MutationObserver(this.sync.queue), this.ownerObserver.observe(e, {
942
- attributes: !0,
1921
+ const ownerId = this.getAttribute("for");
1922
+ if (!ownerId) return void 0;
1923
+ const root = this.getRootNode();
1924
+ const owner = root instanceof ShadowRoot && root.querySelector(`#${CSS.escape(ownerId)}`) || this.ownerDocument.getElementById(ownerId);
1925
+ return owner instanceof HTMLElement ? owner : void 0;
1926
+ }
1927
+ setOwner(owner) {
1928
+ const ownerChanged = this.owner !== owner;
1929
+ if (ownerChanged && this.owner) {
1930
+ this.owner.removeEventListener("focusin", this.onOwnerFocusIn);
1931
+ this.owner.removeEventListener("focusout", this.onOwnerFocusOut);
1932
+ this.owner.removeEventListener("pointerenter", this.onOwnerPointerEnter);
1933
+ this.owner.removeEventListener("pointerleave", this.onInteractivePointerLeave);
1934
+ this.owner.removeEventListener("click", this.onOwnerClick);
1935
+ }
1936
+ this.owner = owner;
1937
+ this.updateManagedDescription(owner);
1938
+ this.ownerObserver?.disconnect();
1939
+ if (!owner) return;
1940
+ this.ownerObserver ??= new MutationObserver(this.sync.queue);
1941
+ this.ownerObserver.observe(owner, {
1942
+ attributes: true,
943
1943
  attributeFilter: [
944
1944
  "aria-describedby",
945
1945
  "aria-disabled",
946
1946
  "disabled"
947
1947
  ]
948
- }), t && (e.addEventListener("focusin", this.onOwnerFocusIn), e.addEventListener("focusout", this.onOwnerFocusOut), e.addEventListener("pointerenter", this.onOwnerPointerEnter), e.addEventListener("pointerleave", this.onInteractivePointerLeave), e.addEventListener("click", this.onOwnerClick)));
1948
+ });
1949
+ if (ownerChanged) {
1950
+ owner.addEventListener("focusin", this.onOwnerFocusIn);
1951
+ owner.addEventListener("focusout", this.onOwnerFocusOut);
1952
+ owner.addEventListener("pointerenter", this.onOwnerPointerEnter);
1953
+ owner.addEventListener("pointerleave", this.onInteractivePointerLeave);
1954
+ owner.addEventListener("click", this.onOwnerClick);
1955
+ }
949
1956
  }
950
1957
  onOwnerFocusIn = () => {
951
- !this.owner || !this.owner.matches(":focus-visible") || this.show(this.owner);
1958
+ if (!this.owner || !this.owner.matches(":focus-visible")) return;
1959
+ this.show(this.owner);
952
1960
  };
953
1961
  onOwnerFocusOut = (e) => {
954
- this.containsInteractiveTarget(e.relatedTarget) || this.hide();
1962
+ if (this.containsInteractiveTarget(e.relatedTarget)) return;
1963
+ this.hide();
955
1964
  };
956
1965
  onOwnerPointerEnter = (e) => {
957
- this.supportsHoverInteraction(e) && this.owner && (this.containsInteractiveTarget(e.relatedTarget) || this.afterDelay(() => this.show(this.owner)));
1966
+ if (!this.supportsHoverInteraction(e)) return;
1967
+ if (!this.owner) return;
1968
+ if (this.containsInteractiveTarget(e.relatedTarget)) return;
1969
+ this.afterDelay(() => this.show(this.owner));
958
1970
  };
959
1971
  onTooltipPointerEnter = (e) => {
960
- this.supportsHoverInteraction(e) && (this.containsInteractiveTarget(e.relatedTarget) || clearTimeout(this.timeout));
1972
+ if (!this.supportsHoverInteraction(e)) return;
1973
+ if (!this.containsInteractiveTarget(e.relatedTarget)) clearTimeout(this.timeout);
961
1974
  };
962
1975
  onInteractivePointerLeave = (e) => {
963
- e.pointerType && e.pointerType !== "mouse" || this.containsInteractiveTarget(e.relatedTarget) || this.afterDelay(this.hide);
1976
+ if (e.pointerType && e.pointerType !== "mouse") return;
1977
+ if (this.containsInteractiveTarget(e.relatedTarget)) return;
1978
+ this.afterDelay(() => this.hide());
964
1979
  };
965
1980
  onOwnerClick = () => {
966
1981
  this.hide();
967
1982
  };
968
- afterDelay(t) {
1983
+ afterDelay(callback) {
969
1984
  clearTimeout(this.timeout);
970
- let n = parseInt(this.getAttribute("delay") || "");
971
- this.timeout = window.setTimeout(t, isNaN(n) ? e.delay : n);
972
- }
973
- containsInteractiveTarget(e) {
974
- return e instanceof Node && (this.contains(e) || !!this.owner && this.owner.contains(e));
975
- }
976
- updateManagedDescription(e) {
977
- let t = e ? this.ensureTooltipId() : void 0;
978
- if (this.managedDescription && (this.managedDescription.owner !== e || this.managedDescription.id !== t)) {
979
- let e = this.managedDescription, t = this.getDescriptionTokens(e.owner).filter((t) => t !== e.id);
980
- t.length ? e.owner.setAttribute("aria-describedby", t.join(" ")) : e.owner.removeAttribute("aria-describedby"), this.managedDescription = void 0;
981
- }
982
- if (!e || !t || this.managedDescription) return;
983
- let n = this.getDescriptionTokens(e);
984
- n.includes(t) || (e.setAttribute("aria-describedby", [...n, t].join(" ")), this.managedDescription = {
985
- owner: e,
986
- id: t
987
- });
1985
+ const delay = parseInt(this.getAttribute("delay") || "");
1986
+ this.timeout = window.setTimeout(callback, isNaN(delay) ? TooltipElement.delay : delay);
1987
+ }
1988
+ containsInteractiveTarget(target) {
1989
+ return target instanceof Node && (this.contains(target) || !!this.owner && this.owner.contains(target));
1990
+ }
1991
+ updateManagedDescription(owner) {
1992
+ const tooltipId = owner ? this.ensureTooltipId() : void 0;
1993
+ if (this.managedDescription && (this.managedDescription.owner !== owner || this.managedDescription.id !== tooltipId)) {
1994
+ const managedDescription = this.managedDescription;
1995
+ const tokens = this.getDescriptionTokens(managedDescription.owner).filter((token) => token !== managedDescription.id);
1996
+ if (tokens.length) managedDescription.owner.setAttribute("aria-describedby", tokens.join(" "));
1997
+ else managedDescription.owner.removeAttribute("aria-describedby");
1998
+ this.managedDescription = void 0;
1999
+ }
2000
+ if (!owner || !tooltipId || this.managedDescription) return;
2001
+ const tokens = this.getDescriptionTokens(owner);
2002
+ if (tokens.includes(tooltipId)) return;
2003
+ owner.setAttribute("aria-describedby", [...tokens, tooltipId].join(" "));
2004
+ this.managedDescription = {
2005
+ owner,
2006
+ id: tooltipId
2007
+ };
988
2008
  }
989
- getDescriptionTokens(e) {
990
- return (e.getAttribute("aria-describedby") || "").split(/\s+/).filter(Boolean);
2009
+ getDescriptionTokens(owner) {
2010
+ return (owner.getAttribute("aria-describedby") || "").split(/\s+/).filter(Boolean);
991
2011
  }
992
2012
  ensureTooltipId() {
993
- return this.id ||= `ui-tooltip-${++ye}`, this.id;
2013
+ if (!this.id) this.id = `ui-tooltip-${++tooltipIdCounter}`;
2014
+ return this.id;
994
2015
  }
995
- supportsHoverInteraction(e) {
996
- return (!e.pointerType || e.pointerType === "mouse") && window.matchMedia("(hover: hover) and (pointer: fine)").matches;
2016
+ supportsHoverInteraction(event) {
2017
+ return (!event.pointerType || event.pointerType === "mouse") && window.matchMedia("(hover: hover) and (pointer: fine)").matches;
997
2018
  }
998
- isOwnerDisabled(e) {
999
- return e.hasAttribute("disabled") || e.getAttribute("aria-disabled") === "true";
2019
+ isOwnerDisabled(owner) {
2020
+ return owner.hasAttribute("disabled") || owner.getAttribute("aria-disabled") === "true";
1000
2021
  }
1001
2022
  };
1002
2023
  //#endregion
1003
- export { j as AlertsElement, I as MenuElement, _e as TabsElement, ve as ToolbarElement, be as TooltipElement };
2024
+ export { AlertsElement, ComboboxElement, MenuElement, TabsElement, ToolbarElement, TooltipElement };