shelving
Version:
Toolkit for using data in JavaScript.
83 lines (82 loc) • 2.95 kB
JavaScript
import { isAsync } from "../../util/async.js";
import { getMessage } from "../../util/error.js";
// Constants.
const NOTICE_EVENT = "notice";
/** MessageEvent */
class NoticeEvent extends CustomEvent {
}
/**
* Notify the user with a message by dispatching a notice event.
* - This is how e.g. `<Button>` and `<FormNotify>` components send notices to the `<Notices>` list of global notices.
*/
export function notify(message, status, el = window) {
el.dispatchEvent(new NoticeEvent(NOTICE_EVENT, {
detail: { message, status },
bubbles: true,
}));
}
/** Notify the user with a success message by dispatching a notice event. */
export function notifySuccess(message, el) {
notify(message, "success", el);
}
/** Notify the user with a success message by dispatching a notice event. */
export function notifyError(message, el) {
notify(message, "error", el);
}
/** Look at a thrown value, extract a viable message from it, and dispatch a notice event.. */
export function notifyThrown(thrown, el) {
const message = getMessage(thrown);
if (message) {
notifyError(message, el);
}
else {
notifyError("Unknown error", el);
console.error(thrown);
}
}
/** Subscribe to notice events on the window and call a callback when they happen. */
export function subscribeNotices(callback, el = window) {
const listener = (e) => {
e.stopPropagation(); // Prevent bubbling to a higher notice subscriber.
if (e instanceof NoticeEvent)
callback(e.detail.message, e.detail.status);
};
el.addEventListener(NOTICE_EVENT, listener);
return () => el.removeEventListener(NOTICE_EVENT, listener);
}
/** Callback that publishes notices to the window if it returns or throws "string" */
export function callNotified(callback, ...args) {
return callNotifiedElement(window, callback, ...args);
}
/** Await a value that publishes "success" or "error" notices to the window if it returns */
export function awaitNotified(pending) {
return awaitNotifiedElement(window, pending);
}
/** Callback that publishes notices to an element (defaults to the window) if it returns or throws "string" */
export function callNotifiedElement(el, callback, ...args) {
try {
const result = callback(...args);
if (isAsync(result))
return awaitNotifiedElement(el, result);
if (result)
notifySuccess(result, el);
return true;
}
catch (thrown) {
notifyThrown(thrown, el);
return false;
}
}
/** Await a value that publishes "success" or "error" notices to an element (defaults to the window) if it returns */
export async function awaitNotifiedElement(el, pending) {
try {
const result = await pending;
if (result)
notifySuccess(result, el);
return true;
}
catch (thrown) {
notifyThrown(thrown, el);
return false;
}
}