diff --git a/src/Noty/Prime/Resources/assets/noty.ts b/src/Noty/Prime/Resources/assets/noty.ts index 7a5a1c16..73ece312 100644 --- a/src/Noty/Prime/Resources/assets/noty.ts +++ b/src/Noty/Prime/Resources/assets/noty.ts @@ -1,40 +1,10 @@ -/** - * @file Noty Plugin Implementation - * @description PHPFlasher integration with the Noty notification library - * @author Younes ENNAJI - */ import { AbstractPlugin } from '@flasher/flasher/dist/plugin' import type { Envelope, Options } from '@flasher/flasher/dist/types' import Noty from 'noty' import type { Type } from 'noty' -/** - * Plugin implementation for Noty notification library. - * - * The NotyPlugin integrates the Noty library with PHPFlasher, allowing - * PHPFlasher to display notifications using Noty's rendering system. - * - * @example - * ```typescript - * import flasher from '@flasher/flasher'; - * import NotyPlugin from '@flasher/flasher-noty'; - * - * // Register the plugin - * flasher.addPlugin('noty', new NotyPlugin()); - * - * // Show a notification - * flasher.use('noty').success('Operation completed'); - * ``` - */ export default class NotyPlugin extends AbstractPlugin { - /** - * Default options for Noty notifications. - * - * These options are applied to all notifications unless overridden. - * - * @private - */ private defaultOptions: { timeout: number [key: string]: any @@ -42,14 +12,6 @@ export default class NotyPlugin extends AbstractPlugin { timeout: 10000, } - /** - * Creates Noty notifications from envelopes. - * - * This method transforms PHPFlasher envelopes into Noty notifications - * and displays them using the Noty library. - * - * @param envelopes - Array of notification envelopes to render - */ public renderEnvelopes(envelopes: Envelope[]): void { if (!envelopes?.length) { return @@ -57,23 +19,19 @@ export default class NotyPlugin extends AbstractPlugin { envelopes.forEach((envelope) => { try { - // Create base options const options: any = { text: envelope.message, type: envelope.type as Type, ...this.defaultOptions, } - // Merge with envelope options if (envelope.options) { Object.assign(options, envelope.options) } - // Create and show the notification const noty = new Noty(options) noty.show() - // Handle Turbo/Hotwire compatibility const layoutDom = (noty as any).layoutDom if (layoutDom && typeof layoutDom.dataset === 'object') { layoutDom.dataset.turboTemporary = '' @@ -84,23 +42,12 @@ export default class NotyPlugin extends AbstractPlugin { }) } - /** - * Apply global options to Noty. - * - * This method configures the Noty library with the provided options, - * which will affect all subsequently created notifications. - * - * @param options - Configuration options for Noty - */ public renderOptions(options: Options): void { if (!options) { return } - // Update default options Object.assign(this.defaultOptions, options) - - // Apply to Noty defaults - use type assertion for compatibility Noty.overrideDefaults(this.defaultOptions) } } diff --git a/src/Prime/Resources/assets/plugin.ts b/src/Prime/Resources/assets/plugin.ts index 51c3fc7b..7eafa3cc 100644 --- a/src/Prime/Resources/assets/plugin.ts +++ b/src/Prime/Resources/assets/plugin.ts @@ -1,138 +1,42 @@ -/** - * @file Abstract Plugin Base Class - * @description Base implementation shared by all notification plugins - * @author Younes ENNAJI - */ import type { Envelope, Options, PluginInterface } from './types' -/** - * Base implementation of a notification plugin. - * - * AbstractPlugin provides default implementations for the standard notification - * methods (success, error, info, warning) that delegate to the flash() method. - * This reduces code duplication and ensures consistent behavior across plugins. - * - * Plugin implementations need only implement the abstract renderEnvelopes() - * and renderOptions() methods to integrate with PHPFlasher. - * - * @example - * ```typescript - * class MyPlugin extends AbstractPlugin { - * // Required implementation - * renderEnvelopes(envelopes: Envelope[]): void { - * // Custom rendering logic - * } - * - * renderOptions(options: Options): void { - * // Custom options handling - * } - * - * // Optional: override other methods if needed - * } - * ``` - */ export abstract class AbstractPlugin implements PluginInterface { - /** - * Render multiple notification envelopes. - * - * Must be implemented by concrete plugins to define how notifications - * are displayed using the specific notification library. - * - * @param envelopes - Array of notification envelopes to render - */ abstract renderEnvelopes(envelopes: Envelope[]): void - /** - * Apply plugin-specific options. - * - * Must be implemented by concrete plugins to configure the underlying - * notification library with the provided options. - * - * @param options - Configuration options for the plugin - */ abstract renderOptions(options: Options): void - /** - * Display a success notification. - * - * @param message - Notification content or options object - * @param title - Optional title or options object - * @param options - Optional configuration options - */ public success(message: string | Options, title?: string | Options, options?: Options): void { this.flash('success', message, title, options) } - /** - * Display an error notification. - * - * @param message - Notification content or options object - * @param title - Optional title or options object - * @param options - Optional configuration options - */ public error(message: string | Options, title?: string | Options, options?: Options): void { this.flash('error', message, title, options) } - /** - * Display an information notification. - * - * @param message - Notification content or options object - * @param title - Optional title or options object - * @param options - Optional configuration options - */ public info(message: string | Options, title?: string | Options, options?: Options): void { this.flash('info', message, title, options) } - /** - * Display a warning notification. - * - * @param message - Notification content or options object - * @param title - Optional title or options object - * @param options - Optional configuration options - */ public warning(message: string | Options, title?: string | Options, options?: Options): void { this.flash('warning', message, title, options) } - /** - * Display any type of notification. - * - * This method handles different parameter formats to provide a flexible API: - * - flash(type, message, title, options) - * - flash(type, message, options) - title in options or just options - * - flash(type, options) - message and title in options - * - flash(options) - type, message, and title in options - * - * @param type - Notification type or options object - * @param message - Notification content or options object - * @param title - Optional title or options object - * @param options - Optional configuration options - * - * @throws {Error} If required parameters are missing - */ public flash(type: string | Options, message: string | Options, title?: string | Options, options?: Options): void { - // Handle overloaded parameters let normalizedType: string let normalizedMessage: string let normalizedTitle: string | undefined let normalizedOptions: Options = {} - // Case: flash({type, message, title, ...options}) if (typeof type === 'object') { normalizedOptions = { ...type } normalizedType = normalizedOptions.type as string normalizedMessage = normalizedOptions.message as string normalizedTitle = normalizedOptions.title as string - // Remove these properties as they're now handled separately delete normalizedOptions.type delete normalizedOptions.message delete normalizedOptions.title - } - // Case: flash(type, {message, title, ...options}) - else if (typeof message === 'object') { + } else if (typeof message === 'object') { normalizedOptions = { ...message } normalizedType = type normalizedMessage = normalizedOptions.message as string @@ -140,26 +44,19 @@ export abstract class AbstractPlugin implements PluginInterface { delete normalizedOptions.message delete normalizedOptions.title - } - // Case: flash(type, message, title|options, options?) - else { + } else { normalizedType = type normalizedMessage = message as string - // Determine if the third parameter is a title string or options object if (title === undefined || title === null) { - // No third parameter normalizedTitle = undefined normalizedOptions = options || {} } else if (typeof title === 'string') { - // Third parameter is a title string normalizedTitle = title normalizedOptions = options || {} } else if (typeof title === 'object') { - // Third parameter is an options object normalizedOptions = { ...title } - // If options has a title property, use it and remove from options if ('title' in normalizedOptions) { normalizedTitle = normalizedOptions.title as string delete normalizedOptions.title @@ -167,14 +64,12 @@ export abstract class AbstractPlugin implements PluginInterface { normalizedTitle = undefined } - // Merge with any options provided in the fourth parameter if (options && typeof options === 'object') { normalizedOptions = { ...normalizedOptions, ...options } } } } - // Validate required parameters if (!normalizedType) { throw new Error('Type is required for notifications') } @@ -183,12 +78,10 @@ export abstract class AbstractPlugin implements PluginInterface { throw new Error('Message is required for notifications') } - // Set title to type if not provided if (normalizedTitle === undefined || normalizedTitle === null) { normalizedTitle = normalizedType.charAt(0).toUpperCase() + normalizedType.slice(1) } - // Create standardized envelope const envelope: Envelope = { type: normalizedType, message: normalizedMessage, @@ -199,7 +92,6 @@ export abstract class AbstractPlugin implements PluginInterface { }, } - // Apply options and render the envelope this.renderOptions({}) this.renderEnvelopes([envelope]) } diff --git a/src/SweetAlert/Prime/Resources/assets/sweetalert.ts b/src/SweetAlert/Prime/Resources/assets/sweetalert.ts index 6a5f48a8..9b3d437e 100644 --- a/src/SweetAlert/Prime/Resources/assets/sweetalert.ts +++ b/src/SweetAlert/Prime/Resources/assets/sweetalert.ts @@ -1,61 +1,20 @@ -/** - * @file SweetAlert Plugin Implementation - * @description PHPFlasher integration with the SweetAlert2 library - * @author Younes ENNAJI - */ import { AbstractPlugin } from '@flasher/flasher/dist/plugin' import type { Envelope, Options } from '@flasher/flasher/dist/types' import type { SweetAlertOptions, SweetAlertResult } from 'sweetalert2' import Swal from 'sweetalert2' -/** Type alias for Swal constructor */ type SwalType = typeof Swal -/** - * Plugin implementation for SweetAlert2 notification library. - * - * The SweetAlertPlugin integrates SweetAlert2 with PHPFlasher, allowing - * for beautiful, responsive modal dialogs with a wide range of customization - * options. - * - * @example - * ```typescript - * import flasher from '@flasher/flasher'; - * import SweetAlertPlugin from '@flasher/flasher-sweetalert'; - * - * // Register the plugin - * flasher.addPlugin('sweetalert', new SweetAlertPlugin()); - * - * // Show a notification - * flasher.use('sweetalert').success('Operation completed'); - * ``` - */ export default class SweetAlertPlugin extends AbstractPlugin { - /** - * The SweetAlert instance used to display notifications. - * Lazy-initialized when first needed. - * - * @private - */ private sweetalert?: SwalType - /** - * Creates SweetAlert notifications from envelopes. - * - * This method processes each envelope sequentially, ensuring - * modals are displayed one after another rather than simultaneously. - * - * @param envelopes - Array of notification envelopes to render - * @returns Promise that resolves when all notifications have been displayed - */ public async renderEnvelopes(envelopes: Envelope[]): Promise { if (!this.sweetalert) { this.initializeSweetAlert() } try { - // Process envelopes sequentially to avoid multiple modals at once for (const envelope of envelopes) { await this.renderEnvelope(envelope) } @@ -64,106 +23,59 @@ export default class SweetAlertPlugin extends AbstractPlugin { } } - /** - * Apply global options to SweetAlert. - * - * This method configures SweetAlert with default options that will - * be applied to all subsequent modal dialogs. - * - * @param options - Configuration options for SweetAlert - */ public renderOptions(options: Options): void { try { - // Create a SweetAlert mixin with default options this.sweetalert = this.sweetalert || Swal.mixin({ - timer: (options.timer || 10000) as unknown, // Default 10 seconds + timer: (options.timer || 10000) as unknown, timerProgressBar: (options.timerProgressBar || true) as unknown, ...options, } as SweetAlertOptions) - // Handle Turbo/Hotwire page transitions this.setupTurboCompatibility() } catch (error) { console.error('PHPFlasher SweetAlert: Error applying options', error) } } - /** - * Render a single notification envelope as a SweetAlert modal. - * - * This method transforms a PHPFlasher envelope into a SweetAlert modal - * and dispatches a custom event with the result for potential listeners. - * - * @param envelope - The notification envelope to render - * @returns Promise that resolves when the modal is closed - * @private - */ private async renderEnvelope(envelope: Envelope): Promise { try { - // Extract and merge options let { options } = envelope - // Set up the SweetAlert options options = { ...options, icon: (options?.icon || envelope.type) as unknown, text: (options?.text || envelope.message) as unknown, } - // Show the modal and get the result const promise = await this.sweetalert?.fire(options as SweetAlertOptions) - - // Dispatch a custom event with the result and envelope this.dispatchResultEvent(promise, envelope) } catch (error) { console.error('PHPFlasher SweetAlert: Error rendering envelope', error, envelope) } } - /** - * Initialize SweetAlert with default options if not already created. - * - * @private - */ private initializeSweetAlert(): void { if (!this.sweetalert) { this.renderOptions({ - timer: 10000, // 10 seconds + timer: 10000, timerProgressBar: true, }) } } - /** - * Set up event listeners for compatibility with Turbo/Hotwire page transitions. - * Ensures modals are properly closed when navigating between pages. - * - * @private - */ private setupTurboCompatibility(): void { - // Close any open modals before Turbo caches the page document.addEventListener('turbo:before-cache', () => { if (Swal.isVisible()) { - // Remove animations to prevent visual glitches during page transitions const popup = Swal.getPopup() if (popup) { popup.style.setProperty('animation-duration', '0ms') } - // Close the modal immediately Swal.close() } }) } - /** - * Dispatch a custom event with the SweetAlert result and envelope. - * This allows external code to react to modal interactions. - * - * @param promise - The result from SweetAlert - * @param envelope - The original notification envelope - * @private - */ private dispatchResultEvent( promise: SweetAlertResult | undefined, envelope: Envelope,