UNPKG

angular-dark-mode

Version:

Add dark mode to your Angular applications with ease!

86 lines 12.1 kB
import { Inject, Injectable, Optional, } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; import { DARK_MODE_OPTIONS } from './dark-mode-options'; import { defaultOptions } from './default-options'; import { isNil } from './isNil'; import * as i0 from "@angular/core"; import * as i1 from "./media-query.service"; export 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: i1.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: i1.MediaQueryService }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DARK_MODE_OPTIONS] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFyay1tb2RlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWRhcmstbW9kZS9zcmMvbGliL2RhcmstbW9kZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxNQUFNLEVBQ04sVUFBVSxFQUNWLFFBQVEsR0FHVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsZUFBZSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDOzs7QUFLaEMsTUFBTSxPQUFPLGVBQWU7SUFLMUIsWUFDVSxlQUFpQyxFQUNqQyxpQkFBb0M7SUFDNUMsa0JBQWtCO0lBQzZCLGVBQXVDO1FBSDlFLG9CQUFlLEdBQWYsZUFBZSxDQUFrQjtRQUNqQyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBRUcsb0JBQWUsR0FBZixlQUFlLENBQXdCO1FBRXRGLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxHQUFHLGNBQWMsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ3RFLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxDQUFDO1FBQzVFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxD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OzZHQXRGVSxlQUFlLG1GQVNKLGlCQUFpQjtpSEFUNUIsZUFBZSxjQURGLE1BQU07NEZBQ25CLGVBQWU7a0JBRDNCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFVN0IsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxpQkFBaUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBJbmplY3QsXG4gIEluamVjdGFibGUsXG4gIE9wdGlvbmFsLFxuICBSZW5kZXJlcjIsXG4gIFJlbmRlcmVyRmFjdG9yeTIsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkaXN0aW5jdFVudGlsQ2hhbmdlZCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IERBUktfTU9ERV9PUFRJT05TIH0gZnJvbSAnLi9kYXJrLW1vZGUtb3B0aW9ucyc7XG5pbXBvcnQgeyBkZWZhdWx0T3B0aW9ucyB9IGZyb20gJy4vZGVmYXVsdC1vcHRpb25zJztcbmltcG9ydCB7IGlzTmlsIH0gZnJvbSAnLi9pc05pbCc7XG5pbXBvcnQgeyBNZWRpYVF1ZXJ5U2VydmljZSB9IGZyb20gJy4vbWVkaWEtcXVlcnkuc2VydmljZSc7XG5pbXBvcnQgeyBEYXJrTW9kZU9wdGlvbnMgfSBmcm9tICcuL3R5cGVzJztcblxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBEYXJrTW9kZVNlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IERhcmtNb2RlT3B0aW9ucztcbiAgcHJpdmF0ZSByZWFkb25seSByZW5kZXJlcjogUmVuZGVyZXIyO1xuICBwcml2YXRlIHJlYWRvbmx5IGRhcmtNb2RlU3ViamVjdCQ6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlbmRlcmVyRmFjdG9yeTogUmVuZGVyZXJGYWN0b3J5MixcbiAgICBwcml2YXRlIG1lZGlhUXVlcnlTZXJ2aWNlOiBNZWRpYVF1ZXJ5U2VydmljZSxcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KERBUktfTU9ERV9PUFRJT05TKSBwcml2YXRlIHByb3ZpZGVkT3B0aW9uczogRGFya01vZGVPcHRpb25zIHwgbnVsbFxuICApIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB7IC4uLmRlZmF1bHRPcHRpb25zLCAuLi4odGhpcy5wcm92aWRlZE9wdGlvbnMgfHwge30pIH07XG4gICAgdGhpcy5yZW5kZXJlciA9IHRoaXMucmVuZGVyZXJGYWN0b3J5LmNyZWF0ZVJlbmRlcmVyKG51bGwsIG51bGwpO1xuICAgIHRoaXMuZGFya01vZGVTdWJqZWN0JCA9IG5ldyBCZWhhdmlvclN1YmplY3QodGhpcy5nZXRJbml0aWFsRGFya01vZGVWYWx1ZSgpKTtcbiAgICB0aGlzLmRhcmtNb2RlU3ViamVjdCQuZ2V0VmFsdWUoKSA/IHRoaXMuZW5hYmxlKCkgOiB0aGlzLmRpc2FibGUoKTtcbiAgICB0aGlzLnJlbW92ZVByZWxvYWRpbmdDbGFzcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIE9ic2VydmFibGUgcmVwcmVzZW50aW5nIGN1cnJlbnQgZGFyayBtb2RlLlxuICAgKiBPbmx5IGZpcmVzIHRoZSBpbml0aWFsIGFuZCBkaXN0aW5jdCB2YWx1ZXMuXG4gICAqL1xuICBnZXQgZGFya01vZGUkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmRhcmtNb2RlU3ViamVjdCQuYXNPYnNlcnZhYmxlKCkucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpKTtcbiAgfVxuXG4gIHRvZ2dsZSgpOiB2b2lkIHtcbiAgICB0aGlzLmRhcmtNb2RlU3ViamVjdCQuZ2V0VmFsdWUoKSA/IHRoaXMuZGlzYWJsZSgpIDogdGhpcy5lbmFibGUoKTtcbiAgfVxuXG4gIGVuYWJsZSgpOiB2b2lkIHtcbiAgICBjb25zdCB7IGVsZW1lbnQsIGRhcmtNb2RlQ2xhc3MsIGxpZ2h0TW9kZUNsYXNzIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyhlbGVtZW50LCBsaWdodE1vZGVDbGFzcyk7XG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhlbGVtZW50LCBkYXJrTW9kZUNsYXNzKTtcbiAgICB0aGlzLnNhdmVEYXJrTW9kZVRvU3RvcmFnZSh0cnVlKTtcbiAgICB0aGlzLmRhcmtNb2RlU3ViamVjdCQubmV4dCh0cnVlKTtcbiAgfVxuXG4gIGRpc2FibGUoKTogdm9pZCB7XG4gICAgY29uc3QgeyBlbGVtZW50LCBkYXJrTW9kZUNsYXNzLCBsaWdodE1vZGVDbGFzcyB9ID0gdGhpcy5vcHRpb25zO1xuICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3MoZWxlbWVudCwgZGFya01vZGVDbGFzcyk7XG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhlbGVtZW50LCBsaWdodE1vZGVDbGFzcyk7XG4gICAgdGhpcy5zYXZlRGFya01vZGVUb1N0b3JhZ2UoZmFsc2UpO1xuICAgIHRoaXMuZGFya01vZGVTdWJqZWN0JC5uZXh0KGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0SW5pdGlhbERhcmtNb2RlVmFsdWUoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZGFya01vZGVGcm9tU3RvcmFnZSA9IHRoaXMuZ2V0RGFya01vZGVGcm9tU3RvcmFnZSgpO1xuXG4gICAgaWYgKGlzTmlsKGRhcmtNb2RlRnJvbVN0b3JhZ2UpKSB7XG4gICAgICByZXR1cm4gdGhpcy5tZWRpYVF1ZXJ5U2VydmljZS5wcmVmZXJzRGFya01vZGUoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGFya01vZGVGcm9tU3RvcmFnZTtcbiAgfVxuXG4gIHByaXZhdGUgc2F2ZURhcmtNb2RlVG9TdG9yYWdlKGRhcmtNb2RlOiBib29sZWFuKTogdm9pZCB7XG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0odGhpcy5vcHRpb25zLnN0b3JhZ2VLZXksIEpTT04uc3RyaW5naWZ5KHsgZGFya01vZGUgfSkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREYXJrTW9kZUZyb21TdG9yYWdlKCk6IGJvb2xlYW4gfCBudWxsIHtcbiAgICBjb25zdCBzdG9yYWdlSXRlbSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMub3B0aW9ucy5zdG9yYWdlS2V5KTtcblxuICAgIGlmIChzdG9yYWdlSXRlbSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2Uoc3RvcmFnZUl0ZW0pPy5kYXJrTW9kZTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgJ0ludmFsaWQgZGFya01vZGUgbG9jYWxTdG9yYWdlIGl0ZW06JyxcbiAgICAgICAgICBzdG9yYWdlSXRlbSxcbiAgICAgICAgICAnZmFsbGluZyBiYWNrIHRvIGNvbG9yIHNjaGVtZSBtZWRpYSBxdWVyeSdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlUHJlbG9hZGluZ0NsYXNzKCk6IHZvaWQge1xuICAgIC8vIGRlZmVyIHRvIG5leHQgdGlja1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyhcbiAgICAgICAgdGhpcy5vcHRpb25zLmVsZW1lbnQsXG4gICAgICAgIHRoaXMub3B0aW9ucy5wcmVsb2FkaW5nQ2xhc3NcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==