@lilydesignsystem/web-components-theme-picker 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +104 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ declare function nextThemePickerId(): string;
|
|
|
77
77
|
declare class ThemePicker extends HTMLElement {
|
|
78
78
|
#private;
|
|
79
79
|
static get observedAttributes(): string[];
|
|
80
|
+
/** id of the rendered `<div class="theme-picker-tooltip">`. */
|
|
81
|
+
get tooltipId(): string;
|
|
80
82
|
get label(): string;
|
|
81
83
|
set label(v: string);
|
|
82
84
|
get themesUrl(): string;
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,59 @@ var ThemePicker = class extends HTMLElement {
|
|
|
59
59
|
#activeIndex = -1;
|
|
60
60
|
// Stable ids for the button/listbox aria wiring.
|
|
61
61
|
#baseId = nextThemePickerId();
|
|
62
|
+
// Tooltip: shown while the pointer is over the button or the tooltip
|
|
63
|
+
// itself (hoverable, WCAG 1.4.13) or while the button has keyboard
|
|
64
|
+
// focus; Escape dismisses it without moving focus; never shown while
|
|
65
|
+
// the popup is open, since the popup then explains the control.
|
|
66
|
+
#tooltipEl = null;
|
|
67
|
+
#hoverButton = false;
|
|
68
|
+
#hoverTooltip = false;
|
|
69
|
+
#focusButton = false;
|
|
70
|
+
#tipDismissed = false;
|
|
71
|
+
// Escape anywhere dismisses a visible tooltip (WCAG 1.4.13: dismissable
|
|
72
|
+
// without moving pointer or focus), so a hover-only tooltip (focus
|
|
73
|
+
// elsewhere) still closes. The document listener exists only while
|
|
74
|
+
// the tooltip is visible; it neither prevents default nor stops
|
|
75
|
+
// propagation, and never moves focus.
|
|
76
|
+
#tipDocListening = false;
|
|
77
|
+
#onTipDocKeydown = (event) => {
|
|
78
|
+
if (event.key === "Escape" && this.#tooltipVisible()) {
|
|
79
|
+
this.#tipDismissed = true;
|
|
80
|
+
this.#syncTooltip();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
#setTipDocListener(on) {
|
|
84
|
+
if (on === this.#tipDocListening || typeof document === "undefined") return;
|
|
85
|
+
this.#tipDocListening = on;
|
|
86
|
+
if (on) document.addEventListener("keydown", this.#onTipDocKeydown);
|
|
87
|
+
else document.removeEventListener("keydown", this.#onTipDocKeydown);
|
|
88
|
+
}
|
|
89
|
+
#tooltipVisible() {
|
|
90
|
+
return !this.#open && !this.#tipDismissed && (this.#hoverButton || this.#hoverTooltip || this.#focusButton);
|
|
91
|
+
}
|
|
92
|
+
/** Write the tooltip's text and `hidden` in place; idempotent. */
|
|
93
|
+
#syncTooltip() {
|
|
94
|
+
const el = this.#tooltipEl;
|
|
95
|
+
if (!el) return;
|
|
96
|
+
if (el.textContent !== this.label) el.textContent = this.label;
|
|
97
|
+
const hide = !this.#tooltipVisible();
|
|
98
|
+
this.#setTipDocListener(!hide);
|
|
99
|
+
if (el.hasAttribute("hidden") !== hide) {
|
|
100
|
+
if (hide) el.setAttribute("hidden", "");
|
|
101
|
+
else el.removeAttribute("hidden");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
#resetTooltip() {
|
|
105
|
+
this.#setTipDocListener(false);
|
|
106
|
+
this.#hoverButton = false;
|
|
107
|
+
this.#hoverTooltip = false;
|
|
108
|
+
this.#focusButton = false;
|
|
109
|
+
this.#tipDismissed = false;
|
|
110
|
+
}
|
|
111
|
+
/** id of the rendered `<div class="theme-picker-tooltip">`. */
|
|
112
|
+
get tooltipId() {
|
|
113
|
+
return `${this.#baseId}-tooltip`;
|
|
114
|
+
}
|
|
62
115
|
// Typeahead buffer: APG listbox behaviour. Reset after a pause.
|
|
63
116
|
#typeahead = "";
|
|
64
117
|
#typeaheadTimer;
|
|
@@ -256,6 +309,7 @@ var ThemePicker = class extends HTMLElement {
|
|
|
256
309
|
}
|
|
257
310
|
}
|
|
258
311
|
disconnectedCallback() {
|
|
312
|
+
this.#resetTooltip();
|
|
259
313
|
document.removeEventListener("click", this.#onDocumentClick);
|
|
260
314
|
clearTimeout(this.#typeaheadTimer);
|
|
261
315
|
this.#appliedValue = "";
|
|
@@ -465,6 +519,7 @@ var ThemePicker = class extends HTMLElement {
|
|
|
465
519
|
*/
|
|
466
520
|
#syncState() {
|
|
467
521
|
if (!this.#rootEl) return;
|
|
522
|
+
this.#syncTooltip();
|
|
468
523
|
const value = this.value;
|
|
469
524
|
if (this.#inputEl) this.#inputEl.value = value;
|
|
470
525
|
if (this.#buttonEl) {
|
|
@@ -515,6 +570,55 @@ var ThemePicker = class extends HTMLElement {
|
|
|
515
570
|
});
|
|
516
571
|
iconButtonHost.addEventListener("keydown", this.#onButtonKeydown);
|
|
517
572
|
root.appendChild(iconButtonHost);
|
|
573
|
+
this.#resetTooltip();
|
|
574
|
+
const tooltip = document.createElement("div");
|
|
575
|
+
tooltip.className = "theme-picker-tooltip";
|
|
576
|
+
tooltip.setAttribute("role", "tooltip");
|
|
577
|
+
tooltip.id = this.tooltipId;
|
|
578
|
+
tooltip.setAttribute("hidden", "");
|
|
579
|
+
tooltip.textContent = this.label;
|
|
580
|
+
tooltip.addEventListener("mouseenter", () => {
|
|
581
|
+
this.#hoverTooltip = true;
|
|
582
|
+
this.#syncTooltip();
|
|
583
|
+
});
|
|
584
|
+
tooltip.addEventListener("mouseleave", () => {
|
|
585
|
+
this.#hoverTooltip = false;
|
|
586
|
+
this.#syncTooltip();
|
|
587
|
+
});
|
|
588
|
+
this.#tooltipEl = tooltip;
|
|
589
|
+
iconButtonHost.addEventListener("mouseenter", () => {
|
|
590
|
+
this.#hoverButton = true;
|
|
591
|
+
this.#tipDismissed = false;
|
|
592
|
+
this.#syncTooltip();
|
|
593
|
+
});
|
|
594
|
+
iconButtonHost.addEventListener("mouseleave", () => {
|
|
595
|
+
this.#hoverButton = false;
|
|
596
|
+
this.#syncTooltip();
|
|
597
|
+
});
|
|
598
|
+
iconButtonHost.addEventListener("click", () => {
|
|
599
|
+
this.#hoverButton = false;
|
|
600
|
+
this.#syncTooltip();
|
|
601
|
+
});
|
|
602
|
+
iconButtonHost.addEventListener("focusin", () => {
|
|
603
|
+
try {
|
|
604
|
+
this.#focusButton = this.#buttonEl?.matches(":focus-visible") ?? false;
|
|
605
|
+
} catch {
|
|
606
|
+
this.#focusButton = true;
|
|
607
|
+
}
|
|
608
|
+
this.#syncTooltip();
|
|
609
|
+
});
|
|
610
|
+
iconButtonHost.addEventListener("focusout", () => {
|
|
611
|
+
this.#focusButton = false;
|
|
612
|
+
this.#tipDismissed = false;
|
|
613
|
+
this.#syncTooltip();
|
|
614
|
+
});
|
|
615
|
+
iconButtonHost.addEventListener("keydown", (event) => {
|
|
616
|
+
if (event.key === "Escape" && this.#tooltipVisible()) {
|
|
617
|
+
this.#tipDismissed = true;
|
|
618
|
+
this.#syncTooltip();
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
root.appendChild(tooltip);
|
|
518
622
|
const list = document.createElement("ul");
|
|
519
623
|
list.className = "theme-picker-list";
|
|
520
624
|
list.id = this.listId;
|