kopia lustrzana https://github.com/shoelace-style/shoelace
Use close watcher when supported in place of escape key handlers (#1788)
* Use close watcher when supported in place of escape key handlers * Update src/components/select/select.component.ts --------- Co-authored-by: Cory LaViska <cory@abeautifulsite.net>pull/1836/head
rodzic
1d626c1357
commit
0a319c3646
|
|
@ -75,6 +75,7 @@ export default class SlDialog extends ShoelaceElement {
|
|||
private readonly localize = new LocalizeController(this);
|
||||
private originalTrigger: HTMLElement | null;
|
||||
public modal = new Modal(this);
|
||||
private closeWatcher: CloseWatcher | null;
|
||||
|
||||
@query('.dialog') dialog: HTMLElement;
|
||||
@query('.dialog__panel') panel: HTMLElement;
|
||||
|
|
@ -112,6 +113,7 @@ export default class SlDialog extends ShoelaceElement {
|
|||
super.disconnectedCallback();
|
||||
this.modal.deactivate();
|
||||
unlockBodyScrolling(this);
|
||||
this.closeWatcher?.destroy();
|
||||
}
|
||||
|
||||
private requestClose(source: 'close-button' | 'keyboard' | 'overlay') {
|
||||
|
|
@ -130,10 +132,17 @@ export default class SlDialog extends ShoelaceElement {
|
|||
}
|
||||
|
||||
private addOpenListeners() {
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
if ('CloseWatcher' in window) {
|
||||
this.closeWatcher?.destroy();
|
||||
this.closeWatcher = new CloseWatcher();
|
||||
this.closeWatcher.onclose = () => this.requestClose('keyboard');
|
||||
} else {
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
}
|
||||
}
|
||||
|
||||
private removeOpenListeners() {
|
||||
this.closeWatcher?.destroy();
|
||||
document.removeEventListener('keydown', this.handleDocumentKeyDown);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ export default class SlDrawer extends ShoelaceElement {
|
|||
private readonly localize = new LocalizeController(this);
|
||||
private originalTrigger: HTMLElement | null;
|
||||
public modal = new Modal(this);
|
||||
private closeWatcher: CloseWatcher | null;
|
||||
|
||||
@query('.drawer') drawer: HTMLElement;
|
||||
@query('.drawer__panel') panel: HTMLElement;
|
||||
|
|
@ -129,6 +130,7 @@ export default class SlDrawer extends ShoelaceElement {
|
|||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
unlockBodyScrolling(this);
|
||||
this.closeWatcher?.destroy();
|
||||
}
|
||||
|
||||
private requestClose(source: 'close-button' | 'keyboard' | 'overlay') {
|
||||
|
|
@ -147,11 +149,20 @@ export default class SlDrawer extends ShoelaceElement {
|
|||
}
|
||||
|
||||
private addOpenListeners() {
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
if ('CloseWatcher' in window) {
|
||||
this.closeWatcher?.destroy();
|
||||
if (!this.contained) {
|
||||
this.closeWatcher = new CloseWatcher();
|
||||
this.closeWatcher.onclose = () => this.requestClose('keyboard');
|
||||
}
|
||||
} else {
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
}
|
||||
}
|
||||
|
||||
private removeOpenListeners() {
|
||||
document.removeEventListener('keydown', this.handleDocumentKeyDown);
|
||||
this.closeWatcher?.destroy();
|
||||
}
|
||||
|
||||
private handleDocumentKeyDown = (event: KeyboardEvent) => {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ export default class SlDropdown extends ShoelaceElement {
|
|||
@query('.dropdown__panel') panel: HTMLSlotElement;
|
||||
|
||||
private readonly localize = new LocalizeController(this);
|
||||
private closeWatcher: CloseWatcher | null;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the dropdown is open. You can toggle this attribute to show and hide the dropdown, or you
|
||||
|
|
@ -149,7 +150,7 @@ export default class SlDropdown extends ShoelaceElement {
|
|||
|
||||
private handleDocumentKeyDown = (event: KeyboardEvent) => {
|
||||
// Close when escape or tab is pressed
|
||||
if (event.key === 'Escape' && this.open) {
|
||||
if (event.key === 'Escape' && this.open && !this.closeWatcher) {
|
||||
event.stopPropagation();
|
||||
this.focusOnTrigger();
|
||||
this.hide();
|
||||
|
|
@ -334,7 +335,16 @@ export default class SlDropdown extends ShoelaceElement {
|
|||
|
||||
addOpenListeners() {
|
||||
this.panel.addEventListener('sl-select', this.handlePanelSelect);
|
||||
this.panel.addEventListener('keydown', this.handleKeyDown);
|
||||
if ('CloseWatcher' in window) {
|
||||
this.closeWatcher?.destroy();
|
||||
this.closeWatcher = new CloseWatcher();
|
||||
this.closeWatcher.onclose = () => {
|
||||
this.hide();
|
||||
this.focusOnTrigger();
|
||||
};
|
||||
} else {
|
||||
this.panel.addEventListener('keydown', this.handleKeyDown);
|
||||
}
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
document.addEventListener('mousedown', this.handleDocumentMouseDown);
|
||||
}
|
||||
|
|
@ -346,6 +356,7 @@ export default class SlDropdown extends ShoelaceElement {
|
|||
}
|
||||
document.removeEventListener('keydown', this.handleDocumentKeyDown);
|
||||
document.removeEventListener('mousedown', this.handleDocumentMouseDown);
|
||||
this.closeWatcher?.destroy();
|
||||
}
|
||||
|
||||
@watch('open', { waitUntilFirstUpdate: true })
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
|
|||
private readonly localize = new LocalizeController(this);
|
||||
private typeToSelectString = '';
|
||||
private typeToSelectTimeout: number;
|
||||
private closeWatcher: CloseWatcher | null;
|
||||
|
||||
@query('.select') popup: SlPopup;
|
||||
@query('.select__combobox') combobox: HTMLSlotElement;
|
||||
|
|
@ -222,6 +223,16 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
|
|||
// https://github.com/shoelace-style/shoelace/issues/1763
|
||||
//
|
||||
const root = this.getRootNode();
|
||||
if ('CloseWatcher' in window) {
|
||||
this.closeWatcher?.destroy();
|
||||
this.closeWatcher = new CloseWatcher();
|
||||
this.closeWatcher.onclose = () => {
|
||||
if (this.open) {
|
||||
this.hide();
|
||||
this.displayInput.focus({ preventScroll: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
root.addEventListener('focusin', this.handleDocumentFocusIn);
|
||||
root.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
root.addEventListener('mousedown', this.handleDocumentMouseDown);
|
||||
|
|
@ -232,6 +243,7 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
|
|||
root.removeEventListener('focusin', this.handleDocumentFocusIn);
|
||||
root.removeEventListener('keydown', this.handleDocumentKeyDown);
|
||||
root.removeEventListener('mousedown', this.handleDocumentMouseDown);
|
||||
this.closeWatcher?.destroy();
|
||||
}
|
||||
|
||||
private handleFocus() {
|
||||
|
|
@ -264,7 +276,7 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
|
|||
}
|
||||
|
||||
// Close when pressing escape
|
||||
if (event.key === 'Escape' && this.open) {
|
||||
if (event.key === 'Escape' && this.open && !this.closeWatcher) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.hide();
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ export default class SlTooltip extends ShoelaceElement {
|
|||
|
||||
private hoverTimeout: number;
|
||||
private readonly localize = new LocalizeController(this);
|
||||
private closeWatcher: CloseWatcher | null;
|
||||
|
||||
@query('slot:not([name])') defaultSlot: HTMLSlotElement;
|
||||
@query('.tooltip__body') body: HTMLElement;
|
||||
|
|
@ -108,6 +109,7 @@ export default class SlTooltip extends ShoelaceElement {
|
|||
|
||||
disconnectedCallback() {
|
||||
// Cleanup this event in case the tooltip is removed while open
|
||||
this.closeWatcher?.destroy();
|
||||
document.removeEventListener('keydown', this.handleDocumentKeyDown);
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +183,13 @@ export default class SlTooltip extends ShoelaceElement {
|
|||
|
||||
// Show
|
||||
this.emit('sl-show');
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
if ('CloseWatcher' in window) {
|
||||
this.closeWatcher?.destroy();
|
||||
this.closeWatcher = new CloseWatcher();
|
||||
this.closeWatcher.onclose = () => { this.hide() };
|
||||
} else {
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
}
|
||||
|
||||
await stopAnimations(this.body);
|
||||
this.body.hidden = false;
|
||||
|
|
@ -194,6 +202,7 @@ export default class SlTooltip extends ShoelaceElement {
|
|||
} else {
|
||||
// Hide
|
||||
this.emit('sl-hide');
|
||||
this.closeWatcher?.destroy();
|
||||
document.removeEventListener('keydown', this.handleDocumentKeyDown);
|
||||
|
||||
await stopAnimations(this.body);
|
||||
|
|
|
|||
|
|
@ -14,3 +14,23 @@ declare namespace Chai {
|
|||
interface HTMLInputElement {
|
||||
showPicker: () => void;
|
||||
}
|
||||
|
||||
interface CloseWatcher extends EventTarget {
|
||||
new (options?: CloseWatcherOptions): CloseWatcher;
|
||||
requestClose(): void;
|
||||
close(): void;
|
||||
destroy(): void;
|
||||
|
||||
oncancel: ((event: Event) => void | null);
|
||||
onclose: ((event: Event) => void | null);
|
||||
}
|
||||
|
||||
declare const CloseWatcher: CloseWatcher;
|
||||
|
||||
interface CloseWatcherOptions {
|
||||
signal: AbortSignal;
|
||||
}
|
||||
|
||||
declare interface Window {
|
||||
CloseWatcher?: CloseWatcher;
|
||||
}
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue