Merge pull request #245 from php-flasher/themes

refactor notyf plugin and improve code documentation
This commit is contained in:
Younes ENNAJI
2025-03-08 11:58:39 +00:00
committed by GitHub
3 changed files with 182 additions and 15 deletions
+38
View File
@@ -1,9 +1,47 @@
/**
* @file Notyf Plugin Entry Point
* @description Registers the Notyf plugin with PHPFlasher
* @author yoeunes
*/
import './notyf.scss'
import flasher from '@flasher/flasher'
import NotyfPlugin from './notyf'
/**
* Create and register the Notyf plugin with PHPFlasher.
*
* This enables using Notyf for displaying notifications through
* the PHPFlasher API.
*
* @example
* ```typescript
* // With the plugin already registered
* import flasher from '@flasher/flasher';
*
* flasher.use('notyf').success('Operation completed');
*
* // With custom options
* flasher.use('notyf').info('This notification has custom options', null, {
* duration: 3000,
* ripple: true,
* dismissible: true
* });
* ```
*/
const notyf = new NotyfPlugin()
flasher.addPlugin('notyf', notyf)
/**
* Export the Notyf plugin instance.
*
* This allows direct access to the plugin if needed.
*
* @example
* ```typescript
* import notyf from '@flasher/flasher-notyf';
*
* notyf.success('Operation completed');
* ```
*/
export default notyf
@@ -1,4 +1,15 @@
/**
* Notyf custom styles for PHPFlasher
*
* These styles define custom icons for additional notification types
* (info and warning) beyond the default success and error types
* provided by Notyf.
*
* @author yoeunes
*/
.notyf {
// Common styles for custom icons
&__icon {
&--warning,
&--info {
@@ -21,6 +32,7 @@
}
}
// Info icon (i)
&--info {
&::before,
&::after {
@@ -31,11 +43,13 @@
transform: translateX(-50%);
}
// Vertical line
&::before {
top: 0.4em;
height: 0.38em;
}
// Dot and shadow
&::after {
top: 0.21em;
height: 0.13em;
@@ -43,6 +57,7 @@
}
}
// Warning icon (!)
&--warning {
&::before,
&::after {
@@ -53,11 +68,13 @@
transform: translateX(-50%);
}
// Exclamation vertical line
&::before {
top: 0.21em;
height: 0.38em;
}
// Exclamation dot
&::after {
top: 0.65em;
height: 0.13em;
+127 -15
View File
@@ -1,3 +1,8 @@
/**
* @file Notyf Plugin Implementation
* @description PHPFlasher integration with the Notyf notification library
* @author yoeunes
*/
import { AbstractPlugin } from '@flasher/flasher/dist/plugin'
import type { Envelope, Options } from '@flasher/flasher/dist/types'
@@ -5,49 +10,156 @@ import { Notyf } from 'notyf'
import type { INotyfOptions } from 'notyf/notyf.options'
import 'notyf/notyf.min.css'
/**
* Plugin implementation for Notyf notification library.
*
* The NotyfPlugin integrates the lightweight Notyf library with PHPFlasher,
* allowing for simple, responsive, and customizable toast notifications.
*
* @example
* ```typescript
* import flasher from '@flasher/flasher';
* import NotyfPlugin from '@flasher/flasher-notyf';
*
* // Register the plugin
* flasher.addPlugin('notyf', new NotyfPlugin());
*
* // Show a notification
* flasher.use('notyf').success('Operation completed');
* ```
*/
export default class NotyfPlugin extends AbstractPlugin {
notyf?: Notyf
/**
* The Notyf instance used to display notifications.
* Lazy-initialized when first needed.
*
* @private
*/
private notyf?: Notyf
/**
* Creates Notyf notifications from envelopes.
*
* This method transforms PHPFlasher envelopes into Notyf notifications
* and displays them using the Notyf library.
*
* @param envelopes - Array of notification envelopes to render
*/
public renderEnvelopes(envelopes: Envelope[]): void {
if (!this.notyf) {
this.initializeNotyf()
}
envelopes.forEach((envelope) => {
const options = { ...envelope, ...envelope.options }
this.notyf?.open(options)
try {
// Merge envelope properties with its options for Notyf compatibility
const options = { ...envelope, ...envelope.options }
this.notyf?.open(options)
} catch (error) {
console.error('PHPFlasher Notyf: Error rendering notification', error, envelope)
}
})
// @ts-expect-error
this.notyf.view.container.dataset.turboTemporary = ''
// @ts-expect-error
this.notyf.view.a11yContainer.dataset.turboTemporary = ''
// Ensure compatibility with Turbo/Hotwire by marking containers
// as temporary elements that should be preserved during page transitions
try {
if (this.notyf) {
// @ts-expect-error - Accessing internal Notyf properties
const container = this.notyf.view.container
// @ts-expect-error - Accessing internal Notyf properties
const a11yContainer = this.notyf.view.a11yContainer
if (container && container.dataset) {
container.dataset.turboTemporary = ''
}
if (a11yContainer && a11yContainer.dataset) {
a11yContainer.dataset.turboTemporary = ''
}
}
} catch (error) {
console.error('PHPFlasher Notyf: Error setting Turbo compatibility', error)
}
}
/**
* Apply global options to Notyf.
*
* This method configures the Notyf library with the provided options,
* which will affect all subsequently created notifications. It also
* adds support for additional notification types beyond the default
* success and error types.
*
* @param options - Configuration options for Notyf
*/
public renderOptions(options: Options): void {
const nOptions = {
duration: options.duration || 5000,
if (!options) {
return
}
const notyfOptions = {
duration: options.duration || 10000, // Default timeout of 10 seconds
...options,
} as unknown as INotyfOptions
nOptions.types = nOptions.types || []
// Initialize types array if not present
notyfOptions.types = notyfOptions.types || []
nOptions.types.push({
// Add support for info notifications with custom icon
this.addTypeIfNotExists(notyfOptions.types, {
type: 'info',
className: 'notyf__toast--info',
background: '#5784E5',
background: '#5784E5', // Blue color
icon: {
className: 'notyf__icon--info',
tagName: 'i',
},
})
nOptions.types.push({
// Add support for warning notifications with custom icon
this.addTypeIfNotExists(notyfOptions.types, {
type: 'warning',
className: 'notyf__toast--warning',
background: '#E3A008',
background: '#E3A008', // Amber color
icon: {
className: 'notyf__icon--warning',
tagName: 'i',
},
})
this.notyf = this.notyf || new Notyf(nOptions as Partial<INotyfOptions>)
// Create or update Notyf instance with new options
this.notyf = this.notyf || new Notyf(notyfOptions)
}
/**
* Initialize the Notyf instance with default options if not already created.
*
* @private
*/
private initializeNotyf(): void {
if (!this.notyf) {
// Default configuration with info and warning types
this.renderOptions({
duration: 10000, // 10 seconds
position: { x: 'right', y: 'top' },
dismissible: true,
})
}
}
/**
* Add a notification type to Notyf if it doesn't already exist.
* Prevents duplicate type definitions.
*
* @param types - Array of notification types
* @param newType - New type to add
* @private
*/
private addTypeIfNotExists(types: any[], newType: any): void {
// Check if type already exists
const exists = types.some((type) => type.type === newType.type)
if (!exists) {
types.push(newType)
}
}
}