Merge pull request #1391 from ae-utbm/notifications-magic

improve `$notifications`
This commit is contained in:
thomas girod
2026-05-20 23:03:30 +02:00
committed by GitHub
11 changed files with 101 additions and 62 deletions
-12
View File
@@ -1,12 +0,0 @@
import sort from "@alpinejs/sort";
import Alpine from "alpinejs";
import { limitedChoices } from "#core:alpine/limited-choices.ts";
import { alpinePlugin as notificationPlugin } from "#core:utils/notifications.ts";
Alpine.plugin([sort, limitedChoices]);
Alpine.magic("notifications", notificationPlugin);
window.Alpine = Alpine;
window.addEventListener("DOMContentLoaded", () => {
Alpine.start();
});
+21
View File
@@ -0,0 +1,21 @@
import sort from "@alpinejs/sort";
import { Alpine } from "alpinejs";
import { limitedChoices } from "#core:alpine/limited-choices";
import {
type NotificationPlugin,
notificationsPlugin as notifications,
} from "#core:utils/notifications";
declare module "alpinejs" {
interface Magics<T> {
$notifications: NotificationPlugin;
}
}
Alpine.plugin([sort, limitedChoices, notifications]);
// biome-ignore lint/style/useNamingConvention: it's how it's named
Object.assign(window, { Alpine });
window.addEventListener("DOMContentLoaded", () => {
Alpine.start();
});
+53 -25
View File
@@ -1,36 +1,64 @@
import { Alpine } from "alpinejs";
export enum NotificationLevel {
Error = "error",
Warning = "warning",
Success = "success",
}
export function createNotification(message: string, level: NotificationLevel) {
const element = document.getElementById("quick-notifications");
if (element === null) {
return false;
}
return element.dispatchEvent(
new CustomEvent("quick-notification-add", {
detail: { text: message, tag: level },
}),
);
export interface NotificationPlugin {
/**
* Add an error message to the notifications.
*/
error: (message: string) => void;
/**
* Add a warning message to the notifications
*/
warning: (message: string) => void;
/**
* Add a success message to the notifications
*/
success: (message: string) => void;
/**
* Remove all notifications displayed on the page.
*/
clear: () => void;
/**
* Add multiple notifications at once.
* The added notifications can have different notification levels.
*/
addMany: (notifs: Notification[]) => void;
/**
* Return all notifications displayed on the page.
*/
getAll: () => Notification[];
}
export function deleteNotifications() {
const element = document.getElementById("quick-notifications");
if (element === null) {
return false;
}
return element.dispatchEvent(new CustomEvent("quick-notification-delete"));
export interface Notification {
tag: NotificationLevel;
text: string;
}
export function alpinePlugin() {
return {
error: (message: string) => createNotification(message, NotificationLevel.Error),
warning: (message: string) =>
createNotification(message, NotificationLevel.Warning),
success: (message: string) =>
createNotification(message, NotificationLevel.Success),
clear: () => deleteNotifications(),
};
Alpine.store("notifications", [] as Notification[]);
function createNotification(message: string, level: NotificationLevel) {
(Alpine.store("notifications") as Notification[]).push({ text: message, tag: level });
}
function createManyNotifications(notifs: Notification[]) {
for (const notif of notifs) {
createNotification(notif.text, notif.tag);
}
}
export const notifications: NotificationPlugin = {
error: (message: string) => createNotification(message, NotificationLevel.Error),
warning: (message: string) => createNotification(message, NotificationLevel.Warning),
success: (message: string) => createNotification(message, NotificationLevel.Success),
clear: () => Alpine.store("notifications", []),
addMany: (notifs: Notification[]) => createManyNotifications(notifs),
getAll: () => Alpine.store("notifications") as Notification[],
};
export function notificationsPlugin(GlobalAlpine: Alpine) {
GlobalAlpine.magic("notifications", () => ({ ...notifications }));
}