ngx-easy-theme-switcher 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # NGX Easy Theme Switcher
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/ngx-easy-theme-switcher)](https://www.npmjs.com/package/ngx-easy-theme-switcher)
4
+ [![Angular](https://img.shields.io/badge/Angular-21.2+-red)](https://angular.dev)
5
+
3
6
  Angular library for easy theme switching (light/dark) with customizable toggle icons.
4
7
 
5
8
  ## Features
@@ -9,6 +12,8 @@ Angular library for easy theme switching (light/dark) with customizable toggle i
9
12
  - **Customizable icon** — default FontAwesome, with support for any icon font or custom SVG
10
13
  - **Standalone** — compatible with Angular standalone components
11
14
  - **Minimal** — just a service and a toggle component
15
+ - **Angular 21** — built and tested with Angular 21.2+
16
+ - **Tested** — unit tests (Jasmine + Karma) and e2e tests (Playwright)
12
17
 
13
18
  ## Installation
14
19
 
@@ -201,8 +206,28 @@ this.themeService.currentTheme$.subscribe(theme => {
201
206
  | `lightIcon` | `'fa-sun'` | Icon name/class for the first theme |
202
207
  | `darkIcon` | `'fa-moon'` | Icon name/class for the second theme |
203
208
 
209
+ ## Testing
210
+
211
+ ```bash
212
+ # Unit tests (library)
213
+ npm run test:lib
214
+
215
+ # Unit tests (demo app)
216
+ npm run test:app
217
+
218
+ # All unit tests in CI mode (single run, headless)
219
+ npm run test:ci
220
+
221
+ # E2E tests (Playwright)
222
+ npm run e2e
223
+ ```
224
+
225
+ ## Changelog
226
+
227
+ See [CHANGELOG.md](./CHANGELOG.md) for the full release history.
228
+
204
229
  ## License
205
230
 
206
- Copyright (c) 2024 **Gennady Artamonov**
231
+ Copyright (c) 2026 **Gennady Artamonov**
207
232
 
208
233
  All use is free. Redistribution or resale of the library itself as a paid product is prohibited. See [LICENSE.md](./LICENSE.md) for full terms.
@@ -68,10 +68,10 @@ class ThemeService {
68
68
  // localStorage not available
69
69
  }
70
70
  }
71
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ThemeService, deps: [{ token: THEME_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
72
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ThemeService, providedIn: 'root' });
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeService, deps: [{ token: THEME_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
72
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeService, providedIn: 'root' });
73
73
  }
74
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ThemeService, decorators: [{
74
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeService, decorators: [{
75
75
  type: Injectable,
76
76
  args: [{
77
77
  providedIn: 'root',
@@ -135,8 +135,8 @@ class ThemeToggleComponent {
135
135
  this.displayIconText = '';
136
136
  }
137
137
  }
138
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ThemeToggleComponent, deps: [{ token: ThemeService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
139
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: ThemeToggleComponent, isStandalone: true, selector: "ets-theme-toggle", inputs: { iconFont: "iconFont", svgIcon: "svgIcon", lightIcon: "lightIcon", darkIcon: "darkIcon" }, ngImport: i0, template: `
138
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeToggleComponent, deps: [{ token: ThemeService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
139
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ThemeToggleComponent, isStandalone: true, selector: "ets-theme-toggle", inputs: { iconFont: "iconFont", svgIcon: "svgIcon", lightIcon: "lightIcon", darkIcon: "darkIcon" }, ngImport: i0, template: `
140
140
  <button
141
141
  class="ets-toggle-btn"
142
142
  (click)="toggle()"
@@ -154,7 +154,7 @@ class ThemeToggleComponent {
154
154
  </button>
155
155
  `, isInline: true, styles: [".ets-toggle-btn{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:8px;border-radius:50%;transition:background-color .3s,color .3s;color:inherit;font-size:1.25rem;line-height:1}.ets-toggle-btn:hover{background-color:#80808026}.ets-icon{display:inline-flex;align-items:center;justify-content:center}.ets-icon--svg{line-height:0}.ets-icon--svg ::ng-deep svg{width:1.25rem;height:1.25rem;fill:currentColor}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
156
156
  }
157
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ThemeToggleComponent, decorators: [{
157
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeToggleComponent, decorators: [{
158
158
  type: Component,
159
159
  args: [{ selector: 'ets-theme-toggle', standalone: true, imports: [NgClass], template: `
160
160
  <button
@@ -1 +1 @@
1
- {"version":3,"file":"ngx-easy-theme-switcher.mjs","sources":["../../../projects/ngx-easy-theme-switcher/src/lib/theme.service.ts","../../../projects/ngx-easy-theme-switcher/src/lib/theme-toggle/theme-toggle.component.ts","../../../projects/ngx-easy-theme-switcher/src/public-api.ts","../../../projects/ngx-easy-theme-switcher/src/ngx-easy-theme-switcher.ts"],"sourcesContent":["import { Injectable, Inject, Optional, InjectionToken } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport interface ThemeConfig {\n /** Names of the two themes, e.g. ['light', 'dark'] */\n themes?: [string, string];\n /** CSS attribute/class to set on the document element */\n attribute?: string;\n /** Storage key for persisting theme preference */\n storageKey?: string;\n /** Default theme (index 0 or 1 from themes array) */\n defaultTheme?: string;\n}\n\nexport const THEME_CONFIG = new InjectionToken<ThemeConfig>('THEME_CONFIG');\n\nconst DEFAULT_CONFIG: ThemeConfig = {\n themes: ['light', 'dark'],\n attribute: 'data-theme',\n storageKey: 'ets-pref-theme',\n defaultTheme: 'light',\n};\n\n@Injectable({\n providedIn: 'root',\n})\nexport class ThemeService {\n private config: ThemeConfig;\n private currentThemeSubject: BehaviorSubject<string>;\n public currentTheme$: Observable<string>;\n\n constructor(@Optional() @Inject(THEME_CONFIG) config?: ThemeConfig) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.currentThemeSubject = new BehaviorSubject<string>(\n this.getStoredTheme()\n );\n this.currentTheme$ = this.currentThemeSubject.asObservable();\n this.applyTheme(this.currentThemeSubject.value);\n }\n\n /** Get the current theme name */\n get currentTheme(): string {\n return this.currentThemeSubject.value;\n }\n\n /** Get all available theme names */\n get themes(): [string, string] {\n return this.config.themes!;\n }\n\n /** Toggle between the two configured themes */\n toggleTheme(): void {\n const [themeA, themeB] = this.config.themes!;\n const next = this.currentTheme === themeA ? themeB : themeA;\n this.setTheme(next);\n }\n\n /** Set a specific theme by name */\n setTheme(theme: string): void {\n if (!this.config.themes!.includes(theme)) {\n console.warn(\n `[EasyThemeSwitcher] Theme \"${theme}\" is not in configured themes:`,\n this.config.themes\n );\n return;\n }\n this.currentThemeSubject.next(theme);\n this.applyTheme(theme);\n this.storeTheme(theme);\n }\n\n private applyTheme(theme: string): void {\n const attr = this.config.attribute!;\n document.documentElement.setAttribute(attr, theme);\n }\n\n private getStoredTheme(): string {\n try {\n const stored = localStorage.getItem(this.config.storageKey!);\n if (stored && this.config.themes!.includes(stored)) {\n return stored;\n }\n } catch {\n // localStorage not available\n }\n return this.config.defaultTheme!;\n }\n\n private storeTheme(theme: string): void {\n try {\n localStorage.setItem(this.config.storageKey!, theme);\n } catch {\n // localStorage not available\n }\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';\nimport { NgClass } from '@angular/common';\nimport { Subject, takeUntil } from 'rxjs';\nimport { ThemeService } from '../theme.service';\n\nexport type IconFont =\n | 'fas' // FontAwesome Solid\n | 'far' // FontAwesome Regular\n | 'fal' // FontAwesome Light\n | 'fab' // FontAwesome Brands\n | 'material-icons'\n | 'material-icons-outlined'\n | 'material-symbols-outlined'\n | 'bi' // Bootstrap Icons\n | 'pi' // PrimeIcons\n | 'ion-icon'; // Ionicons\n\n@Component({\n selector: 'ets-theme-toggle',\n standalone: true,\n imports: [NgClass],\n template: `\n <button\n class=\"ets-toggle-btn\"\n (click)=\"toggle()\"\n [attr.aria-label]=\"'Switch to ' + oppositeTheme + ' mode'\"\n type=\"button\"\n >\n @if (svgIcon) {\n <span class=\"ets-icon ets-icon--svg\" [innerHTML]=\"svgIcon\"></span>\n } @else {\n <span\n class=\"ets-icon\"\n [ngClass]=\"iconClasses\"\n >{{ displayIconText }}</span>\n }\n </button>\n `,\n styles: `\n .ets-toggle-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: background-color 0.3s, color 0.3s;\n color: inherit;\n font-size: 1.25rem;\n line-height: 1;\n }\n .ets-toggle-btn:hover {\n background-color: rgba(128, 128, 128, 0.15);\n }\n .ets-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .ets-icon--svg {\n line-height: 0;\n }\n .ets-icon--svg ::ng-deep svg {\n width: 1.25rem;\n height: 1.25rem;\n fill: currentColor;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ThemeToggleComponent implements OnInit, OnDestroy {\n /** Icon font abbreviation (e.g. 'fas', 'material-icons', 'bi') */\n @Input() iconFont?: IconFont;\n\n /** Custom SVG markup (overrides iconFont if provided) */\n @Input() svgIcon?: string;\n\n /** Icon name for the first theme (default light) */\n @Input() lightIcon?: string;\n\n /** Icon name for the second theme (default dark) */\n @Input() darkIcon?: string;\n\n protected oppositeTheme = '';\n protected iconClasses: Record<string, boolean> = {};\n protected displayIconText = '';\n\n private destroy$ = new Subject<void>();\n\n constructor(\n private themeService: ThemeService,\n private cdr: ChangeDetectorRef,\n ) {}\n\n ngOnInit(): void {\n this.updateState(this.themeService.currentTheme);\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe((theme) => {\n this.updateState(theme);\n this.cdr.markForCheck();\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n toggle(): void {\n this.themeService.toggleTheme();\n }\n\n private updateState(currentTheme: string): void {\n const [lightTheme, darkTheme] = this.themeService.themes;\n const isLight = currentTheme === lightTheme;\n\n this.oppositeTheme = currentTheme === lightTheme ? darkTheme : lightTheme;\n\n const iconName = isLight\n ? (this.darkIcon ?? 'fa-moon')\n : (this.lightIcon ?? 'fa-sun');\n\n const font = this.iconFont ?? 'fas';\n\n if (font.startsWith('material')) {\n this.iconClasses = { [font]: true };\n this.displayIconText = iconName;\n } else {\n this.iconClasses = { [font]: true, [iconName]: true };\n this.displayIconText = '';\n }\n }\n}\n","/*\r\n * Public API Surface of ngx-easy-theme-switcher\r\n */\r\n\r\nexport { ThemeService, THEME_CONFIG } from './lib/theme.service';\r\nexport type { ThemeConfig } from './lib/theme.service';\r\nexport { ThemeToggleComponent } from './lib/theme-toggle/theme-toggle.component';\r\nexport type { IconFont } from './lib/theme-toggle/theme-toggle.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.ThemeService"],"mappings":"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"}
1
+ {"version":3,"file":"ngx-easy-theme-switcher.mjs","sources":["../../../projects/ngx-easy-theme-switcher/src/lib/theme.service.ts","../../../projects/ngx-easy-theme-switcher/src/lib/theme-toggle/theme-toggle.component.ts","../../../projects/ngx-easy-theme-switcher/src/public-api.ts","../../../projects/ngx-easy-theme-switcher/src/ngx-easy-theme-switcher.ts"],"sourcesContent":["import { Injectable, Inject, Optional, InjectionToken } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport interface ThemeConfig {\n /** Names of the two themes, e.g. ['light', 'dark'] */\n themes?: [string, string];\n /** CSS attribute/class to set on the document element */\n attribute?: string;\n /** Storage key for persisting theme preference */\n storageKey?: string;\n /** Default theme (index 0 or 1 from themes array) */\n defaultTheme?: string;\n}\n\nexport const THEME_CONFIG = new InjectionToken<ThemeConfig>('THEME_CONFIG');\n\nconst DEFAULT_CONFIG: ThemeConfig = {\n themes: ['light', 'dark'],\n attribute: 'data-theme',\n storageKey: 'ets-pref-theme',\n defaultTheme: 'light',\n};\n\n@Injectable({\n providedIn: 'root',\n})\nexport class ThemeService {\n private config: ThemeConfig;\n private currentThemeSubject: BehaviorSubject<string>;\n public currentTheme$: Observable<string>;\n\n constructor(@Optional() @Inject(THEME_CONFIG) config?: ThemeConfig) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.currentThemeSubject = new BehaviorSubject<string>(\n this.getStoredTheme()\n );\n this.currentTheme$ = this.currentThemeSubject.asObservable();\n this.applyTheme(this.currentThemeSubject.value);\n }\n\n /** Get the current theme name */\n get currentTheme(): string {\n return this.currentThemeSubject.value;\n }\n\n /** Get all available theme names */\n get themes(): [string, string] {\n return this.config.themes!;\n }\n\n /** Toggle between the two configured themes */\n toggleTheme(): void {\n const [themeA, themeB] = this.config.themes!;\n const next = this.currentTheme === themeA ? themeB : themeA;\n this.setTheme(next);\n }\n\n /** Set a specific theme by name */\n setTheme(theme: string): void {\n if (!this.config.themes!.includes(theme)) {\n console.warn(\n `[EasyThemeSwitcher] Theme \"${theme}\" is not in configured themes:`,\n this.config.themes\n );\n return;\n }\n this.currentThemeSubject.next(theme);\n this.applyTheme(theme);\n this.storeTheme(theme);\n }\n\n private applyTheme(theme: string): void {\n const attr = this.config.attribute!;\n document.documentElement.setAttribute(attr, theme);\n }\n\n private getStoredTheme(): string {\n try {\n const stored = localStorage.getItem(this.config.storageKey!);\n if (stored && this.config.themes!.includes(stored)) {\n return stored;\n }\n } catch {\n // localStorage not available\n }\n return this.config.defaultTheme!;\n }\n\n private storeTheme(theme: string): void {\n try {\n localStorage.setItem(this.config.storageKey!, theme);\n } catch {\n // localStorage not available\n }\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';\nimport { NgClass } from '@angular/common';\nimport { Subject, takeUntil } from 'rxjs';\nimport { ThemeService } from '../theme.service';\n\nexport type IconFont =\n | 'fas' // FontAwesome Solid\n | 'far' // FontAwesome Regular\n | 'fal' // FontAwesome Light\n | 'fab' // FontAwesome Brands\n | 'material-icons'\n | 'material-icons-outlined'\n | 'material-symbols-outlined'\n | 'bi' // Bootstrap Icons\n | 'pi' // PrimeIcons\n | 'ion-icon'; // Ionicons\n\n@Component({\n selector: 'ets-theme-toggle',\n standalone: true,\n imports: [NgClass],\n template: `\n <button\n class=\"ets-toggle-btn\"\n (click)=\"toggle()\"\n [attr.aria-label]=\"'Switch to ' + oppositeTheme + ' mode'\"\n type=\"button\"\n >\n @if (svgIcon) {\n <span class=\"ets-icon ets-icon--svg\" [innerHTML]=\"svgIcon\"></span>\n } @else {\n <span\n class=\"ets-icon\"\n [ngClass]=\"iconClasses\"\n >{{ displayIconText }}</span>\n }\n </button>\n `,\n styles: `\n .ets-toggle-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: background-color 0.3s, color 0.3s;\n color: inherit;\n font-size: 1.25rem;\n line-height: 1;\n }\n .ets-toggle-btn:hover {\n background-color: rgba(128, 128, 128, 0.15);\n }\n .ets-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .ets-icon--svg {\n line-height: 0;\n }\n .ets-icon--svg ::ng-deep svg {\n width: 1.25rem;\n height: 1.25rem;\n fill: currentColor;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ThemeToggleComponent implements OnInit, OnDestroy {\n /** Icon font abbreviation (e.g. 'fas', 'material-icons', 'bi') */\n @Input() iconFont?: IconFont;\n\n /** Custom SVG markup (overrides iconFont if provided) */\n @Input() svgIcon?: string;\n\n /** Icon name for the first theme (default light) */\n @Input() lightIcon?: string;\n\n /** Icon name for the second theme (default dark) */\n @Input() darkIcon?: string;\n\n protected oppositeTheme = '';\n protected iconClasses: Record<string, boolean> = {};\n protected displayIconText = '';\n\n private destroy$ = new Subject<void>();\n\n constructor(\n private themeService: ThemeService,\n private cdr: ChangeDetectorRef,\n ) {}\n\n ngOnInit(): void {\n this.updateState(this.themeService.currentTheme);\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe((theme) => {\n this.updateState(theme);\n this.cdr.markForCheck();\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n toggle(): void {\n this.themeService.toggleTheme();\n }\n\n private updateState(currentTheme: string): void {\n const [lightTheme, darkTheme] = this.themeService.themes;\n const isLight = currentTheme === lightTheme;\n\n this.oppositeTheme = currentTheme === lightTheme ? darkTheme : lightTheme;\n\n const iconName = isLight\n ? (this.darkIcon ?? 'fa-moon')\n : (this.lightIcon ?? 'fa-sun');\n\n const font = this.iconFont ?? 'fas';\n\n if (font.startsWith('material')) {\n this.iconClasses = { [font]: true };\n this.displayIconText = iconName;\n } else {\n this.iconClasses = { [font]: true, [iconName]: true };\n this.displayIconText = '';\n }\n }\n}\n","/*\r\n * Public API Surface of ngx-easy-theme-switcher\r\n */\r\n\r\nexport { ThemeService, THEME_CONFIG } from './lib/theme.service';\r\nexport type { ThemeConfig } from './lib/theme.service';\r\nexport { ThemeToggleComponent } from './lib/theme-toggle/theme-toggle.component';\r\nexport type { IconFont } from './lib/theme-toggle/theme-toggle.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.ThemeService"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-easy-theme-switcher",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A lightweight Angular service and component for seamless dark/light theme switching. Supports FontAwesome, Material Icons, Bootstrap Icons, custom SVG icons, and popular icon fonts out of the box. Persistent theme selection with localStorage.",
5
5
  "keywords": [
6
6
  "angular",
@@ -30,22 +30,23 @@
30
30
  "url": "https://github.com/cyclon-b/ngx-easy-theme-switcher.git"
31
31
  },
32
32
  "peerDependencies": {
33
- "@angular/common": "^19.2.0",
34
- "@angular/core": "^19.2.0"
33
+ "@angular/common": "^21.2.0",
34
+ "@angular/core": "^21.2.0"
35
35
  },
36
36
  "dependencies": {
37
37
  "tslib": "^2.3.0"
38
38
  },
39
39
  "sideEffects": false,
40
40
  "module": "fesm2022/ngx-easy-theme-switcher.mjs",
41
- "typings": "index.d.ts",
41
+ "typings": "types/ngx-easy-theme-switcher.d.ts",
42
42
  "exports": {
43
43
  "./package.json": {
44
44
  "default": "./package.json"
45
45
  },
46
46
  ".": {
47
- "types": "./index.d.ts",
47
+ "types": "./types/ngx-easy-theme-switcher.d.ts",
48
48
  "default": "./fesm2022/ngx-easy-theme-switcher.mjs"
49
49
  }
50
- }
50
+ },
51
+ "type": "module"
51
52
  }
@@ -0,0 +1,62 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
3
+ import { Observable } from 'rxjs';
4
+
5
+ interface ThemeConfig {
6
+ /** Names of the two themes, e.g. ['light', 'dark'] */
7
+ themes?: [string, string];
8
+ /** CSS attribute/class to set on the document element */
9
+ attribute?: string;
10
+ /** Storage key for persisting theme preference */
11
+ storageKey?: string;
12
+ /** Default theme (index 0 or 1 from themes array) */
13
+ defaultTheme?: string;
14
+ }
15
+ declare const THEME_CONFIG: InjectionToken<ThemeConfig>;
16
+ declare class ThemeService {
17
+ private config;
18
+ private currentThemeSubject;
19
+ currentTheme$: Observable<string>;
20
+ constructor(config?: ThemeConfig);
21
+ /** Get the current theme name */
22
+ get currentTheme(): string;
23
+ /** Get all available theme names */
24
+ get themes(): [string, string];
25
+ /** Toggle between the two configured themes */
26
+ toggleTheme(): void;
27
+ /** Set a specific theme by name */
28
+ setTheme(theme: string): void;
29
+ private applyTheme;
30
+ private getStoredTheme;
31
+ private storeTheme;
32
+ static ɵfac: i0.ɵɵFactoryDeclaration<ThemeService, [{ optional: true; }]>;
33
+ static ɵprov: i0.ɵɵInjectableDeclaration<ThemeService>;
34
+ }
35
+
36
+ type IconFont = 'fas' | 'far' | 'fal' | 'fab' | 'material-icons' | 'material-icons-outlined' | 'material-symbols-outlined' | 'bi' | 'pi' | 'ion-icon';
37
+ declare class ThemeToggleComponent implements OnInit, OnDestroy {
38
+ private themeService;
39
+ private cdr;
40
+ /** Icon font abbreviation (e.g. 'fas', 'material-icons', 'bi') */
41
+ iconFont?: IconFont;
42
+ /** Custom SVG markup (overrides iconFont if provided) */
43
+ svgIcon?: string;
44
+ /** Icon name for the first theme (default light) */
45
+ lightIcon?: string;
46
+ /** Icon name for the second theme (default dark) */
47
+ darkIcon?: string;
48
+ protected oppositeTheme: string;
49
+ protected iconClasses: Record<string, boolean>;
50
+ protected displayIconText: string;
51
+ private destroy$;
52
+ constructor(themeService: ThemeService, cdr: ChangeDetectorRef);
53
+ ngOnInit(): void;
54
+ ngOnDestroy(): void;
55
+ toggle(): void;
56
+ private updateState;
57
+ static ɵfac: i0.ɵɵFactoryDeclaration<ThemeToggleComponent, never>;
58
+ static ɵcmp: i0.ɵɵComponentDeclaration<ThemeToggleComponent, "ets-theme-toggle", never, { "iconFont": { "alias": "iconFont"; "required": false; }; "svgIcon": { "alias": "svgIcon"; "required": false; }; "lightIcon": { "alias": "lightIcon"; "required": false; }; "darkIcon": { "alias": "darkIcon"; "required": false; }; }, {}, never, never, true, never>;
59
+ }
60
+
61
+ export { THEME_CONFIG, ThemeService, ThemeToggleComponent };
62
+ export type { IconFont, ThemeConfig };
package/index.d.ts DELETED
@@ -1,5 +0,0 @@
1
- /**
2
- * Generated bundle index. Do not edit.
3
- */
4
- /// <amd-module name="ngx-easy-theme-switcher" />
5
- export * from './public-api';
@@ -1,27 +0,0 @@
1
- import { ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';
2
- import { ThemeService } from '../theme.service';
3
- import * as i0 from "@angular/core";
4
- export type IconFont = 'fas' | 'far' | 'fal' | 'fab' | 'material-icons' | 'material-icons-outlined' | 'material-symbols-outlined' | 'bi' | 'pi' | 'ion-icon';
5
- export declare class ThemeToggleComponent implements OnInit, OnDestroy {
6
- private themeService;
7
- private cdr;
8
- /** Icon font abbreviation (e.g. 'fas', 'material-icons', 'bi') */
9
- iconFont?: IconFont;
10
- /** Custom SVG markup (overrides iconFont if provided) */
11
- svgIcon?: string;
12
- /** Icon name for the first theme (default light) */
13
- lightIcon?: string;
14
- /** Icon name for the second theme (default dark) */
15
- darkIcon?: string;
16
- protected oppositeTheme: string;
17
- protected iconClasses: Record<string, boolean>;
18
- protected displayIconText: string;
19
- private destroy$;
20
- constructor(themeService: ThemeService, cdr: ChangeDetectorRef);
21
- ngOnInit(): void;
22
- ngOnDestroy(): void;
23
- toggle(): void;
24
- private updateState;
25
- static ɵfac: i0.ɵɵFactoryDeclaration<ThemeToggleComponent, never>;
26
- static ɵcmp: i0.ɵɵComponentDeclaration<ThemeToggleComponent, "ets-theme-toggle", never, { "iconFont": { "alias": "iconFont"; "required": false; }; "svgIcon": { "alias": "svgIcon"; "required": false; }; "lightIcon": { "alias": "lightIcon"; "required": false; }; "darkIcon": { "alias": "darkIcon"; "required": false; }; }, {}, never, never, true, never>;
27
- }
@@ -1,33 +0,0 @@
1
- import { InjectionToken } from '@angular/core';
2
- import { Observable } from 'rxjs';
3
- import * as i0 from "@angular/core";
4
- export interface ThemeConfig {
5
- /** Names of the two themes, e.g. ['light', 'dark'] */
6
- themes?: [string, string];
7
- /** CSS attribute/class to set on the document element */
8
- attribute?: string;
9
- /** Storage key for persisting theme preference */
10
- storageKey?: string;
11
- /** Default theme (index 0 or 1 from themes array) */
12
- defaultTheme?: string;
13
- }
14
- export declare const THEME_CONFIG: InjectionToken<ThemeConfig>;
15
- export declare class ThemeService {
16
- private config;
17
- private currentThemeSubject;
18
- currentTheme$: Observable<string>;
19
- constructor(config?: ThemeConfig);
20
- /** Get the current theme name */
21
- get currentTheme(): string;
22
- /** Get all available theme names */
23
- get themes(): [string, string];
24
- /** Toggle between the two configured themes */
25
- toggleTheme(): void;
26
- /** Set a specific theme by name */
27
- setTheme(theme: string): void;
28
- private applyTheme;
29
- private getStoredTheme;
30
- private storeTheme;
31
- static ɵfac: i0.ɵɵFactoryDeclaration<ThemeService, [{ optional: true; }]>;
32
- static ɵprov: i0.ɵɵInjectableDeclaration<ThemeService>;
33
- }
package/public-api.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export { ThemeService, THEME_CONFIG } from './lib/theme.service';
2
- export type { ThemeConfig } from './lib/theme.service';
3
- export { ThemeToggleComponent } from './lib/theme-toggle/theme-toggle.component';
4
- export type { IconFont } from './lib/theme-toggle/theme-toggle.component';