blob: 714955bbacc78a50571bb8b0aaf6dd0bc2000673 [file] [log] [blame]
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {FetchRequest} from '../types/types';
import {
DialogChangeEventDetail,
EventType,
SwitchTabEventDetail,
TabState,
} from '../types/events';
export function fireEvent(target: EventTarget, type: string) {
target.dispatchEvent(
new CustomEvent(type, {
composed: true,
bubbles: true,
})
);
}
export type HTMLElementEventDetailType<K extends keyof HTMLElementEventMap> =
HTMLElementEventMap[K] extends CustomEvent<infer DT>
? unknown extends DT
? never
: DT
: never;
type DocumentEventDetailType<K extends keyof DocumentEventMap> =
DocumentEventMap[K] extends CustomEvent<infer DT>
? unknown extends DT
? never
: DT
: never;
export function fire<K extends keyof DocumentEventMap>(
target: Document,
type: K,
detail: DocumentEventDetailType<K>
): void;
export function fire<K extends keyof HTMLElementEventMap>(
target: EventTarget,
type: K,
detail: HTMLElementEventDetailType<K>
): void;
export function fire<T>(target: EventTarget, type: string, detail: T) {
target.dispatchEvent(
new CustomEvent<T>(type, {
detail,
composed: true,
bubbles: true,
})
);
}
export function fireAlert(target: EventTarget, message: string) {
fire(target, EventType.SHOW_ALERT, {message, showDismiss: true});
}
export function firePageError(response?: Response | null) {
if (response === null) response = undefined;
fire(document, EventType.PAGE_ERROR, {response});
}
export function fireServerError(response: Response, request?: FetchRequest) {
fire(document, EventType.SERVER_ERROR, {
response,
request,
});
}
export function fireNetworkError(error: Error) {
fire(document, EventType.NETWORK_ERROR, {error});
}
export function fireTitleChange(target: EventTarget, title: string) {
fire(target, EventType.TITLE_CHANGE, {title});
}
// TODO(milutin) - remove once new gr-dialog will do it out of the box
// This informs gr-app-element to remove footer, header from a11y tree
export function fireDialogChange(
target: EventTarget,
detail: DialogChangeEventDetail
) {
fire(target, EventType.DIALOG_CHANGE, detail);
}
export function fireIronAnnounce(target: EventTarget, text: string) {
fire(target, EventType.IRON_ANNOUNCE, {text});
}
export function fireShowTab(
target: EventTarget,
tab: string,
scrollIntoView?: boolean,
tabState?: TabState
) {
const detail: SwitchTabEventDetail = {tab, scrollIntoView, tabState};
fire(target, EventType.SHOW_TAB, detail);
}
export function fireCloseFixPreview(target: EventTarget, fixApplied: boolean) {
fire(target, EventType.CLOSE_FIX_PREVIEW, {fixApplied});
}
export function fireReload(target: EventTarget, clearPatchset?: boolean) {
fire(target, EventType.RELOAD, {clearPatchset: !!clearPatchset});
}
export function waitForEventOnce<K extends keyof HTMLElementEventMap>(
el: EventTarget,
eventName: K
): Promise<HTMLElementEventMap[K]> {
return new Promise<HTMLElementEventMap[K]>(resolve => {
const callback = (event: HTMLElementEventMap[K]) => {
resolve(event);
};
el.addEventListener(eventName, callback as EventListener, {once: true});
});
}