diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 2d07c46..5162536 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -35,3 +35,6 @@ jobs: - name: Build demo run: npm run build:demo + + - name: Build standalone demo + run: npm run build:standalone-demo \ No newline at end of file diff --git a/README.md b/README.md index 154d696..e4ff728 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ **A fully animated, highly customizable, and easy-to-use notification library for Angular applications** -[![Build & Test](https://img.shields.io/github/actions/workflow/status/Gramli/angular-notifier/ci.yml?style=flat-square&label=Build)](https://github.com/Gramli/angular-notifier/actions/workflows/ci.yml) +[![Build & Test](https://img.shields.io/github/actions/workflow/status/Gramli/angular-notifier/build-and-test.yml?style=flat-square&label=Build)](https://github.com/Gramli/angular-notifier/actions/workflows/build-and-test.yml) [![npm version](https://img.shields.io/npm/v/gramli-angular-notifier?style=flat-square&logo=npm)](https://www.npmjs.com/package/gramli-angular-notifier) [![Angular](https://img.shields.io/badge/Angular-21.x-dd0031?style=flat-square&logo=angular)](https://angular.io) [![License](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)](LICENSE) -[Features](#features) • [Installation](#installation) • [Quick Start](#quick-start) • [Themes](#themes) • [API](#api) • [Customization](#customization) +[Features](#features) • [Installation](#installation) • [Quick Start](#quick-start) • [Examples](#live-examples) • [Themes](#themes) • [API](#api) • [Customization](#customization) ![Angular Notifier Animated Preview](https://raw.githubusercontent.com/Gramli/angular-notifier/develop/docs/angular-notifier-preview.gif) @@ -27,6 +27,7 @@ Angular Notifier is a notification library designed to provide elegant, non-intr - **Type-safe** - Written in TypeScript with full type definitions - **Lightweight** - Zero dependencies beyond Angular itself - **Production-ready** - Battle-tested and actively maintained +- **Module & Standalone support** - Works with both traditional NgModule and modern standalone components ## Features @@ -64,6 +65,8 @@ npm install gramli-angular-notifier ### 1. Import the NotifierModule +#### For Module-Based Applications + Add the `NotifierModule` to your root module: ```typescript @@ -71,22 +74,51 @@ import { NotifierModule } from 'gramli-angular-notifier'; @NgModule({ imports: [ - NotifierModule, - // Or with custom configuration + // With custom configuration NotifierModule.withConfig({ position: { horizontal: { position: 'right', distance: 12 }, vertical: { position: 'top', distance: 12, gap: 10 } }, theme: 'material' - }) + }), + // Or with default configuration + NotifierModule.withConfig() ] }) export class AppModule { } ``` -> **Note**: This library currently requires NgModule-based applications and is not yet compatible with standalone components. -### 2. Add the notifier container +> **Important**: As of version 21.1.x, you must use `NotifierModule.withConfig()` even for default configuration. Simply importing `NotifierModule` without calling `withConfig()` will not provide the required services. + +#### For Standalone Applications + +Use the `provideNotifier()` function in your application configuration: + +```typescript +// main.ts or app.config.ts +import { ApplicationConfig } from '@angular/core'; +import { provideNotifier } from 'gramli-angular-notifier'; + +export const appConfig: ApplicationConfig = { + providers: [ + // With custom configuration + provideNotifier({ + position: { + horizontal: { position: 'right', distance: 12 }, + vertical: { position: 'top', distance: 12, gap: 10 } + }, + theme: 'material' + }), + // Or with default configuration + // provideNotifier() + ] +}; +``` + +### 2. AppComponent - Add the notifier container + +#### For Module-Based Applications Add the `` component to your app component template: @@ -101,6 +133,26 @@ Add the `` component to your app component template: export class AppComponent { } ``` +#### For Standalone Applications + +Add the `` component to your app component template and import `NotifierModule` in components that display notifications: + +```typescript +import { Component } from '@angular/core'; +import { NotifierModule } from 'gramli-angular-notifier'; + +@Component({ + selector: 'app-root', + standalone: true, + imports: [NotifierModule], // Import for components only + template: ` + + + ` +}) +export class AppComponent { } +``` + ### 3. Import styles Import the styles in your global styles file (`styles.scss` or `styles.css`): @@ -138,6 +190,16 @@ export class ExampleComponent { } ``` +## Live Examples + +Explore complete working examples demonstrating both module-based and standalone approaches: + +### 📦 [Module-Based Demo](https://github.com/Gramli/angular-notifier/tree/develop/projects/angular-notifier-demo) +Full example application using traditional NgModule architecture with `NotifierModule.withConfig()`. + +### ⚡ [Standalone Demo](https://github.com/Gramli/angular-notifier/tree/develop/projects/angular-notifier-standalone-demo) +Modern standalone component example using `provideNotifier()` in application configuration. + ## Themes Angular Notifier comes with three professionally designed themes: @@ -511,11 +573,33 @@ Check that animations are enabled in your configuration: NotifierModule.withConfig({ animations: { enabled: true } }) ``` -## Credits +### Breaking Change in v21.x: Module imports + +If you're upgrading from an earlier version and see errors like "No provider for NotifierService" or notifications not appearing: + +**Problem**: In v21.1.x, `NotifierModule` no longer provides services by default when imported alone. + +**Solution**: Update your imports to use `withConfig()`: -This library is a maintained fork of [angular-notifier](https://github.com/dominique-mueller/angular-notifier) by Dominique Müller. Special thanks to the original author for creating this excellent library. +```typescript +// Before (v20.x and earlier) +@NgModule({ + imports: [NotifierModule] +}) + +// After (v21.1.x) +@NgModule({ + imports: [ + NotifierModule.withConfig() // Use withConfig() even for default settings + ] +}) +``` + +This change was made to support proper configuration in standalone applications and ensure consistent behavior across different application architectures. + +## Credits -Originally created by [itsdevdom](https://github.com/itsdevdom). Currently maintained by [Gramli](https://github.com/Gramli). +Originally created by [dominique-mueller](https://github.com/itsdevdom). Currently maintained by [Gramli](https://github.com/Gramli). ## License diff --git a/angular.json b/angular.json index aba85ef..d2b2edb 100644 --- a/angular.json +++ b/angular.json @@ -88,6 +88,74 @@ } } } + }, + "angular-notifier-standalone-demo": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "root": "projects/angular-notifier-standalone-demo", + "sourceRoot": "projects/angular-notifier-standalone-demo/src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular/build:application", + "options": { + "browser": "projects/angular-notifier-standalone-demo/src/main.ts", + "tsConfig": "projects/angular-notifier-standalone-demo/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "projects/angular-notifier-standalone-demo/public" + } + ], + "styles": [ + "projects/angular-notifier-standalone-demo/src/styles.scss" + ] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kB", + "maximumError": "1MB" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "4kB", + "maximumError": "8kB" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular/build:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-notifier-standalone-demo:build:production" + }, + "development": { + "buildTarget": "angular-notifier-standalone-demo:build:development" + } + }, + "defaultConfiguration": "development" + }, + "test": { + "builder": "@angular/build:unit-test" + } + } } } } diff --git a/package-lock.json b/package-lock.json index 9ca66c6..1ee74c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gramli-angular-notifier", - "version": "21.0.0", + "version": "21.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gramli-angular-notifier", - "version": "21.0.0", + "version": "21.1.0", "license": "MIT", "dependencies": { "tslib": "2.8.x" diff --git a/package.json b/package.json index 4bffed0..429cc3c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gramli-angular-notifier", "description": "A well designed, fully animated, highly customizable, and easy-to-use notification library for your Angular application.", - "version": "21.0.0", + "version": "21.1.0", "license": "MIT", "repository": { "type": "git", @@ -26,12 +26,17 @@ "popup", "angular-component", "angular-library", + "angular-standalone", + "standalone", + "standalone-components", + "ngmodule", "typescript", "animated", "customizable" ], "scripts": { "build:demo": "ng build angular-notifier-demo --configuration production", + "build:standalone-demo": "ng build angular-notifier-standalone-demo --configuration production", "build:library": "rimraf dist && npm run build:library:angular && npm run build:library:sass && npm run build:library:css && npm run build:library:docs && npm run build:library:package", "build:library:angular": "ng build angular-notifier --configuration production", "build:library:css": "sass projects/angular-notifier/src:dist/angular-notifier --style=expanded", @@ -41,6 +46,7 @@ "lint:library": "eslint projects/angular-notifier/src/**/*.ts --max-warnings 0", "lint:library:fix": "eslint projects/angular-notifier/src/**/*.ts --max-warnings 0 --fix", "start": "ng serve angular-notifier-demo", + "start:standalone": "ng serve angular-notifier-standalone-demo", "test:library": "ng test angular-notifier", "test:library:watch": "ng test angular-notifier --watch", "test:library:upload-coverage": "codecov -f coverage/coverage-final.json" diff --git a/projects/angular-notifier-standalone-demo/src/app/app.config.ts b/projects/angular-notifier-standalone-demo/src/app/app.config.ts new file mode 100644 index 0000000..070dd1b --- /dev/null +++ b/projects/angular-notifier-standalone-demo/src/app/app.config.ts @@ -0,0 +1,23 @@ +import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core'; + +import { provideNotifier } from 'angular-notifier'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideBrowserGlobalErrorListeners(), + provideNotifier({ + position: { + horizontal: { + position: 'right', + distance: 12, + }, + vertical: { + position: 'bottom', + distance: 12, + gap: 10, + }, + }, + theme: 'primeng', + }), + ], +}; diff --git a/projects/angular-notifier-standalone-demo/src/app/app.html b/projects/angular-notifier-standalone-demo/src/app/app.html new file mode 100644 index 0000000..50cf04d --- /dev/null +++ b/projects/angular-notifier-standalone-demo/src/app/app.html @@ -0,0 +1,66 @@ + + +
+

Show notifications

+ + + + + + + +

Hide notifications

+ + + + +

Show & hide a specific notification

+ + + +
+ Configuration Tip: You can play with the configuration, it's located in the + angular-notifier-demo/src/app/app.module.ts file. +
+
+ Theme Tip: Default theme is material, available themes: material, bootstrap, primeng. +
+
+ + + + +
+ {{ notification.type }}: {{ notification.message }} +
+
diff --git a/projects/angular-notifier-standalone-demo/src/app/app.scss b/projects/angular-notifier-standalone-demo/src/app/app.scss new file mode 100644 index 0000000..9c94a18 --- /dev/null +++ b/projects/angular-notifier-standalone-demo/src/app/app.scss @@ -0,0 +1,73 @@ +.navbar { + background: #2b82b1; + height: 60px; + display: flex; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + position: sticky; + top: 0; + z-index: 1000; + justify-content: space-between; + align-items: center; +} + +.navbar-brand { + color: #ffffff; + font-size: 20px; + font-weight: 700; + letter-spacing: -0.5px; + padding-left: 1rem; +} + +.navbar-icons { + display: flex; + gap: 16px; + align-items: center; + padding-right: 1rem; +} + +.icon-link { + color: #ffffff; + display: flex; + align-items: center; + justify-content: center; + padding: 8px; + border-radius: var(--radius-sm); + transition: var(--transition); + text-decoration: none; +} + +.icon-link:hover { + background: rgba(255, 255, 255, 0.15); + transform: translateY(-2px); +} + +.icon-link svg { + width: 24px; + height: 24px; +} + +.content { + padding-left: 2rem; +} + +.tip { + margin: 1rem; + padding: 1rem; + margin-bottom: 20px; + background-color: #f0f8ff; + border-left: 4px solid #2b90d9; + border-radius: 4px; + color: #333; +} + +.tip strong { + color: #2b90d9; +} + +.tip code { + background-color: #e8e8e8; + padding: 2px 6px; + border-radius: 3px; + font-family: 'Courier New', Courier, monospace; + font-size: 13px; +} \ No newline at end of file diff --git a/projects/angular-notifier-standalone-demo/src/app/app.ts b/projects/angular-notifier-standalone-demo/src/app/app.ts new file mode 100644 index 0000000..d73c5c8 --- /dev/null +++ b/projects/angular-notifier-standalone-demo/src/app/app.ts @@ -0,0 +1,95 @@ +import { Component, ViewChild } from '@angular/core'; +import { NotifierModule, NotifierService } from 'angular-notifier'; + +@Component({ + selector: 'app-root', + imports: [NotifierModule], + templateUrl: './app.html', + styleUrl: './app.scss', +}) +export class App { + @ViewChild('customTemplate', { static: true }) customNotificationTmpl; + + /** + * Notifier service + */ + private notifier: NotifierService; + + /** + * Constructor + * + * @param {NotifierService} notifier Notifier service + */ + public constructor(notifier: NotifierService) { + this.notifier = notifier; + } + + /** + * Show a notification + * + * @param {string} type Notification type + * @param {string} message Notification message + */ + public showNotification(type: string, message: string): void { + this.notifier.notify(type, message); + } + + /** + * Hide oldest notification + */ + public hideOldestNotification(): void { + this.notifier.hideOldest(); + } + + /** + * Hide newest notification + */ + public hideNewestNotification(): void { + this.notifier.hideNewest(); + } + + /** + * Hide all notifications at once + */ + public hideAllNotifications(): void { + this.notifier.hideAll(); + } + + /** + * Show custom notification using template + * + * @param {string} type Notification type + * @param {string} message Notification message + */ + public showCustomNotificationTemplate(type: string, message: string): void { + this.notifier.show({ + message, + type, + template: this.customNotificationTmpl, + }); + } + + /** + * Show a specific notification (with a custom notification ID) + * + * @param {string} type Notification type + * @param {string} message Notification message + * @param {string} id Notification ID + */ + public showSpecificNotification(type: string, message: string, id: string): void { + this.notifier.show({ + id, + message, + type, + }); + } + + /** + * Hide a specific notification (by a given notification ID) + * + * @param {string} id Notification ID + */ + public hideSpecificNotification(id: string): void { + this.notifier.hide(id); + } +} diff --git a/projects/angular-notifier-standalone-demo/src/index.html b/projects/angular-notifier-standalone-demo/src/index.html new file mode 100644 index 0000000..c6d6f37 --- /dev/null +++ b/projects/angular-notifier-standalone-demo/src/index.html @@ -0,0 +1,13 @@ + + + + + AngularNotifierStandaloneDemo + + + + + + + + diff --git a/projects/angular-notifier-standalone-demo/src/main.ts b/projects/angular-notifier-standalone-demo/src/main.ts new file mode 100644 index 0000000..5df75f9 --- /dev/null +++ b/projects/angular-notifier-standalone-demo/src/main.ts @@ -0,0 +1,6 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { App } from './app/app'; + +bootstrapApplication(App, appConfig) + .catch((err) => console.error(err)); diff --git a/projects/angular-notifier-standalone-demo/src/styles.scss b/projects/angular-notifier-standalone-demo/src/styles.scss new file mode 100644 index 0000000..a51288e --- /dev/null +++ b/projects/angular-notifier-standalone-demo/src/styles.scss @@ -0,0 +1,76 @@ +@use '../../angular-notifier/src/styles'; + +/* BASIC */ + +html { + width: 100%; + height: 100%; +} + +body { + width: 100%; + height: 100%; + margin: 0; + box-sizing: border-box; + font-family: 'Roboto', 'Tahoma', 'Trebuchet MS', 'Arial', 'Helvetica', sans-serif; + font-size: 14px; +} + +* { + box-sizing: inherit; +} + +/* APP */ + +.app { + display: block; +} + +/* HEADINGS */ + +h1 { + font-size: 30px; + padding-bottom: 10px; +} + +h2 { + margin-top: 40px; + font-size: 18px; +} + +/* BUTTONS */ + +.button { + display: inline-block; + padding: 11px 16px 10px; + margin-right: 4px; + background: none; + border: none; + border-radius: 2px; + cursor: pointer; + opacity: 1; + -webkit-transition: background-color 0.2s ease; + transition: background-color 0.2s ease; +} + +.button--primary { + background-color: #2b90d9; + color: #fff; +} + +.button--primary:hover, +.button--primary:focus, +.button--primary:active { + background-color: #2273ad; +} + +.button--secondary { + background-color: #ddd; + color: #333; +} + +.button--secondary:hover, +.button--secondary:focus, +.button--secondary:active { + background-color: #cacaca; +} diff --git a/projects/angular-notifier-standalone-demo/tsconfig.app.json b/projects/angular-notifier-standalone-demo/tsconfig.app.json new file mode 100644 index 0000000..742c488 --- /dev/null +++ b/projects/angular-notifier-standalone-demo/tsconfig.app.json @@ -0,0 +1,15 @@ +/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ +/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/app", + "types": [] + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "src/**/*.spec.ts" + ] +} diff --git a/projects/angular-notifier/src/lib/notifier.module.spec.ts b/projects/angular-notifier/src/lib/notifier.module.spec.ts index 982ec3d..182f581 100644 --- a/projects/angular-notifier/src/lib/notifier.module.spec.ts +++ b/projects/angular-notifier/src/lib/notifier.module.spec.ts @@ -2,8 +2,10 @@ import { TestBed } from '@angular/core/testing'; import { describe, expect, it } from 'vitest'; import { NotifierConfig, NotifierOptions } from './models/notifier-config.model'; -import { NotifierModule } from './notifier.module'; +import { NotifierModule, provideNotifier } from './notifier.module'; import { NotifierService } from './services/notifier.service'; +import { NotifierAnimationService } from './services/notifier-animation.service'; +import { NotifierQueueService } from './services/notifier-queue.service'; /** * Notifier Module - Unit Test @@ -11,7 +13,7 @@ import { NotifierService } from './services/notifier.service'; describe('Notifier Module', () => { it('should instantiate', () => { TestBed.configureTestingModule({ - imports: [NotifierModule], + imports: [NotifierModule.withConfig()], }); const service: NotifierService = TestBed.inject(NotifierService); @@ -20,7 +22,7 @@ describe('Notifier Module', () => { it('should instantiate with default options', () => { TestBed.configureTestingModule({ - imports: [NotifierModule], + imports: [NotifierModule.withConfig()], }); const service: NotifierService = TestBed.inject(NotifierService); @@ -98,3 +100,113 @@ describe('Notifier Module', () => { expect(service.getConfig()).toEqual(expectedNotifierConfig); }); }); + +/** + * provideNotifier Function - Unit Test + */ +describe('provideNotifier Function', () => { + it('should provide all necessary services and default configuration', () => { + TestBed.configureTestingModule({ + imports: [NotifierModule], + providers: [provideNotifier()], + }); + + const service = TestBed.inject(NotifierService); + const animationService = TestBed.inject(NotifierAnimationService); + const queueService = TestBed.inject(NotifierQueueService); + + expect(service).toBeDefined(); + expect(animationService).toBeDefined(); + expect(queueService).toBeDefined(); + expect(service.getConfig()).toEqual(new NotifierConfig()); + }); + + it('should provide services with custom configuration', () => { + const testNotifierOptions: NotifierOptions = { + animations: { + hide: { + easing: 'ease-in-out', + }, + overlap: 100, + shift: { + speed: 200, + }, + }, + behaviour: { + autoHide: 5000, + stacking: 7, + }, + position: { + horizontal: { + distance: 20, + }, + }, + theme: 'my-custom-theme', + }; + const expectedNotifierConfig: NotifierConfig = new NotifierConfig({ + animations: { + enabled: true, + hide: { + easing: 'ease-in-out', + offset: 50, + preset: 'fade', + speed: 300, + }, + overlap: 100, + shift: { + easing: 'ease', + speed: 200, + }, + show: { + easing: 'ease', + preset: 'slide', + speed: 300, + }, + }, + behaviour: { + autoHide: 5000, + onClick: false, + onMouseover: 'pauseAutoHide', + showDismissButton: true, + stacking: 7, + }, + position: { + horizontal: { + distance: 20, + position: 'left', + }, + vertical: { + distance: 12, + gap: 10, + position: 'bottom', + }, + }, + theme: 'my-custom-theme', + }); + + TestBed.configureTestingModule({ + imports: [NotifierModule], + providers: [provideNotifier(testNotifierOptions)], + }); + + const service = TestBed.inject(NotifierService); + expect(service.getConfig()).toEqual(expectedNotifierConfig); + }); + + it('should work in standalone component context', () => { + TestBed.configureTestingModule({ + imports: [NotifierModule], + providers: [ + provideNotifier({ + theme: 'material', + behaviour: { autoHide: 3000 }, + }), + ], + }); + + const service = TestBed.inject(NotifierService); + expect(service).toBeDefined(); + expect(service.getConfig().theme).toBe('material'); + expect(service.getConfig().behaviour.autoHide).toBe(3000); + }); +}); diff --git a/projects/angular-notifier/src/lib/notifier.module.ts b/projects/angular-notifier/src/lib/notifier.module.ts index e7e255b..7851cd2 100644 --- a/projects/angular-notifier/src/lib/notifier.module.ts +++ b/projects/angular-notifier/src/lib/notifier.module.ts @@ -1,5 +1,5 @@ import { CommonModule } from '@angular/common'; -import { ModuleWithProviders, NgModule } from '@angular/core'; +import { ModuleWithProviders, NgModule, Provider } from '@angular/core'; import { NotifierContainerComponent } from './components/notifier-container.component'; import { NotifierNotificationComponent } from './components/notifier-notification.component'; @@ -35,23 +35,54 @@ export function notifierDefaultConfigFactory(): NotifierConfig { } /** - * Notifier module + * Provide notifier configuration for standalone applications + * + * This function should be used in the application bootstrap providers (main.ts) + * to configure the notifier globally. Import NotifierModule in components that need it. + * + * @example + * ```typescript + * import { bootstrapApplication } from '@angular/platform-browser'; + * import { provideNotifier } from 'angular-notifier'; + * + * bootstrapApplication(AppComponent, { + * providers: [provideNotifier({ theme: 'material' })] + * }); + * + * @Component({ + * standalone: true, + * imports: [NotifierModule], // Just import, config comes from bootstrap + * }) + * export class AppComponent {} + * ``` + * + * @param [options={}] - Custom notifier options + * @returns - Array of providers for the notifier configuration */ -@NgModule({ - declarations: [NotifierContainerComponent, NotifierNotificationComponent], - exports: [NotifierContainerComponent], - imports: [CommonModule], - providers: [ +export function provideNotifier(options: NotifierOptions = {}): Provider[] { + return [ NotifierAnimationService, NotifierService, NotifierQueueService, - - // Provide the default notifier configuration if just the module is imported { + provide: NotifierOptionsToken, + useValue: options, + }, + { + deps: [NotifierOptionsToken], provide: NotifierConfigToken, - useFactory: notifierDefaultConfigFactory, + useFactory: notifierCustomConfigFactory, }, - ], + ]; +} + +/** + * Notifier module + */ +@NgModule({ + declarations: [NotifierContainerComponent, NotifierNotificationComponent], + exports: [NotifierContainerComponent], + imports: [CommonModule], }) export class NotifierModule { /** @@ -64,6 +95,11 @@ export class NotifierModule { return { ngModule: NotifierModule, providers: [ + // Provide the services + NotifierAnimationService, + NotifierService, + NotifierQueueService, + // Provide the options itself upfront (as we need to inject them as dependencies -- see below) { provide: NotifierOptionsToken,