UNPKG

angular-dark-mode

Version:

Add dark mode to your Angular applications with ease!

144 lines (134 loc) 5.49 kB
import * as i0 from '@angular/core'; import { InjectionToken, Injectable, Optional, Inject } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; /** * InjectionToken to override default options * * @example * * providers: [ * { * provide: DARK_MODE_OPTIONS, * useValue: { * darkModeClass: 'my-dark-mode', * lightModeClass: 'my-light-mode', * }, * }, * ] */ const DARK_MODE_OPTIONS = new InjectionToken('DARK_MODE_OPTIONS'); /** * Default options used in DarkModeService */ const defaultOptions = { darkModeClass: 'dark-mode', lightModeClass: 'light-mode', preloadingClass: 'dark-mode-preloading', storageKey: 'dark-mode', element: document.body, }; /* eslint-disable @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any */ function isNil(value) { return value === null || value === undefined; } const prefersDarkSchemeQuery = '(prefers-color-scheme: dark)'; class MediaQueryService { matchMedia(query) { return window.matchMedia(query); } prefersDarkMode() { return this.matchMedia(prefersDarkSchemeQuery).matches; } } MediaQueryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: MediaQueryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); MediaQueryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: MediaQueryService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: MediaQueryService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class DarkModeService { constructor(rendererFactory, mediaQueryService, // prettier-ignore providedOptions) { this.rendererFactory = rendererFactory; this.mediaQueryService = mediaQueryService; this.providedOptions = providedOptions; this.options = { ...defaultOptions, ...(this.providedOptions || {}) }; this.renderer = this.rendererFactory.createRenderer(null, null); this.darkModeSubject$ = new BehaviorSubject(this.getInitialDarkModeValue()); this.darkModeSubject$.getValue() ? this.enable() : this.disable(); this.removePreloadingClass(); } /** * An Observable representing current dark mode. * Only fires the initial and distinct values. */ get darkMode$() { return this.darkModeSubject$.asObservable().pipe(distinctUntilChanged()); } toggle() { this.darkModeSubject$.getValue() ? this.disable() : this.enable(); } enable() { const { element, darkModeClass, lightModeClass } = this.options; this.renderer.removeClass(element, lightModeClass); this.renderer.addClass(element, darkModeClass); this.saveDarkModeToStorage(true); this.darkModeSubject$.next(true); } disable() { const { element, darkModeClass, lightModeClass } = this.options; this.renderer.removeClass(element, darkModeClass); this.renderer.addClass(element, lightModeClass); this.saveDarkModeToStorage(false); this.darkModeSubject$.next(false); } getInitialDarkModeValue() { const darkModeFromStorage = this.getDarkModeFromStorage(); if (isNil(darkModeFromStorage)) { return this.mediaQueryService.prefersDarkMode(); } return darkModeFromStorage; } saveDarkModeToStorage(darkMode) { localStorage.setItem(this.options.storageKey, JSON.stringify({ darkMode })); } getDarkModeFromStorage() { const storageItem = localStorage.getItem(this.options.storageKey); if (storageItem) { try { return JSON.parse(storageItem)?.darkMode; } catch (error) { console.error('Invalid darkMode localStorage item:', storageItem, 'falling back to color scheme media query'); } } return null; } removePreloadingClass() { // defer to next tick setTimeout(() => { this.renderer.removeClass(this.options.element, this.options.preloadingClass); }); } } DarkModeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: DarkModeService, deps: [{ token: i0.RendererFactory2 }, { token: MediaQueryService }, { token: DARK_MODE_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); DarkModeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: DarkModeService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: DarkModeService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: function () { return [{ type: i0.RendererFactory2 }, { type: MediaQueryService }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DARK_MODE_OPTIONS] }] }]; } }); /* * Public API Surface of angular-dark-mode */ /** * Generated bundle index. Do not edit. */ export { DARK_MODE_OPTIONS, DarkModeService }; //# sourceMappingURL=angular-dark-mode.mjs.map