Simplify JSDoc comments in plugin TypeScript files

Removes verbose documentation from:
- plugin.ts (AbstractPlugin base class)
- noty.ts (Noty plugin implementation)
- sweetalert.ts (SweetAlert plugin implementation)

Keeps essential type annotations.
This commit is contained in:
Younes ENNAJI
2026-01-16 00:28:35 +01:00
parent 613c73d7b6
commit cc9fa57c4a
3 changed files with 4 additions and 253 deletions
-53
View File
@@ -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)
}
}
+2 -110
View File
@@ -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])
}
@@ -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<void> {
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<void> {
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<any> | undefined,
envelope: Envelope,