@tolle_/tolle-ui 0.0.2-beta → 0.0.3-beta

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.
@@ -0,0 +1,82 @@
1
+ import { Injectable, Inject, PLATFORM_ID, Optional } from '@angular/core';
2
+ import { DOCUMENT, isPlatformBrowser } from '@angular/common';
3
+ import { BehaviorSubject } from 'rxjs';
4
+ import { TOLLE_CONFIG } from './tolle-config';
5
+ import * as i0 from "@angular/core";
6
+ export class ThemeService {
7
+ document;
8
+ platformId;
9
+ config;
10
+ renderer;
11
+ isDarkSubject = new BehaviorSubject(false);
12
+ isDark$ = this.isDarkSubject.asObservable();
13
+ constructor(document, platformId, config, rendererFactory) {
14
+ this.document = document;
15
+ this.platformId = platformId;
16
+ this.config = config;
17
+ this.renderer = rendererFactory.createRenderer(null, null);
18
+ this.initializeTheme();
19
+ }
20
+ initializeTheme() {
21
+ if (!isPlatformBrowser(this.platformId))
22
+ return;
23
+ // 1. Determine Initial Mode (Dark/Light)
24
+ const savedTheme = localStorage.getItem('tolle-theme');
25
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
26
+ // Priority: Saved Preference > Config Default > System Preference
27
+ const shouldBeDark = savedTheme
28
+ ? savedTheme === 'dark'
29
+ : (this.config?.darkByDefault ?? prefersDark);
30
+ if (shouldBeDark) {
31
+ this.enableDarkMode();
32
+ }
33
+ else {
34
+ this.disableDarkMode();
35
+ }
36
+ // 2. Apply Brand Config (Colors/Radius)
37
+ if (this.config) {
38
+ this.applyBrandConfig(this.config);
39
+ }
40
+ }
41
+ applyBrandConfig(config) {
42
+ const root = this.document.documentElement;
43
+ if (config.primaryColor) {
44
+ this.renderer.setStyle(root, '--primary', config.primaryColor);
45
+ }
46
+ if (config.radius) {
47
+ this.renderer.setStyle(root, '--radius', config.radius);
48
+ }
49
+ }
50
+ toggleTheme() {
51
+ const isDark = this.document.documentElement.classList.contains('dark');
52
+ isDark ? this.disableDarkMode() : this.enableDarkMode();
53
+ }
54
+ enableDarkMode() {
55
+ this.renderer.addClass(this.document.documentElement, 'dark');
56
+ localStorage.setItem('tolle-theme', 'dark');
57
+ this.isDarkSubject.next(true);
58
+ }
59
+ disableDarkMode() {
60
+ this.renderer.removeClass(this.document.documentElement, 'dark');
61
+ localStorage.setItem('tolle-theme', 'light');
62
+ this.isDarkSubject.next(false);
63
+ }
64
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: TOLLE_CONFIG, optional: true }, { token: i0.RendererFactory2 }], target: i0.ɵɵFactoryTarget.Injectable });
65
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, providedIn: 'root' });
66
+ }
67
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, decorators: [{
68
+ type: Injectable,
69
+ args: [{ providedIn: 'root' }]
70
+ }], ctorParameters: () => [{ type: Document, decorators: [{
71
+ type: Inject,
72
+ args: [DOCUMENT]
73
+ }] }, { type: Object, decorators: [{
74
+ type: Inject,
75
+ args: [PLATFORM_ID]
76
+ }] }, { type: undefined, decorators: [{
77
+ type: Optional
78
+ }, {
79
+ type: Inject,
80
+ args: [TOLLE_CONFIG]
81
+ }] }, { type: i0.RendererFactory2 }] });
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhlbWUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvdGhlbWUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUErQixNQUFNLGVBQWUsQ0FBQztBQUN2RyxPQUFPLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN2QyxPQUFPLEVBQUUsWUFBWSxFQUFlLE1BQU0sZ0JBQWdCLENBQUM7O0FBRzNELE1BQU0sT0FBTyxZQUFZO0lBTUs7SUFDRztJQUNhO0lBUHBDLFFBQVEsQ0FBWTtJQUNwQixhQUFhLEdBQUcsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7SUFDNUQsT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLENBQUM7SUFFNUMsWUFDNEIsUUFBa0IsRUFDZixVQUFrQixFQUNMLE1BQW1CLEVBQzdELGVBQWlDO1FBSFAsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNmLGVBQVUsR0FBVixVQUFVLENBQVE7UUFDTCxXQUFNLEdBQU4sTUFBTSxDQUFhO1FBRzdELElBQUksQ0FBQyxRQUFRLEdBQUcsZUFBZSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDM0QsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFTyxlQUFlO1FBQ3JCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO1lBQUUsT0FBTztRQUVoRCx5Q0FBeUM7UUFDekMsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN2RCxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLDhCQUE4QixDQUFDLENBQUMsT0FBTyxDQUFDO1FBRTlFLGtFQUFrRTtRQUNsRSxNQUFNLFlBQVksR0FBRyxVQUFVO1lBQzdCLENBQUMsQ0FBQyxVQUFVLEtBQUssTUFBTTtZQUN2QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLGFBQWEsSUFBSSxXQUFXLENBQUMsQ0FBQztRQUVoRCxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ2pCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN4QixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN6QixDQUFDO1FBRUQsd0NBQXdDO1FBQ3hDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckMsQ0FBQztJQUNILENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxNQUFtQjtRQUMxQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQztRQUMzQyxJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNqRSxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUQsQ0FBQztJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4RSxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQzFELENBQUM7SUFFTyxjQUFjO1FBQ3BCLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzlELFlBQVksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFTyxlQUFlO1FBQ3JCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2pFLFlBQVksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzdDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLENBQUM7d0dBaEVVLFlBQVksa0JBTWIsUUFBUSxhQUNSLFdBQVcsYUFDQyxZQUFZOzRHQVJ2QixZQUFZLGNBREMsTUFBTTs7NEZBQ25CLFlBQVk7a0JBRHhCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFPN0IsTUFBTTsyQkFBQyxRQUFROzswQkFDZixNQUFNOzJCQUFDLFdBQVc7OzBCQUNsQixRQUFROzswQkFBSSxNQUFNOzJCQUFDLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBJbmplY3QsIFBMQVRGT1JNX0lELCBPcHRpb25hbCwgUmVuZGVyZXIyLCBSZW5kZXJlckZhY3RvcnkyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBET0NVTUVOVCwgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBUT0xMRV9DT05GSUcsIFRvbGxlQ29uZmlnIH0gZnJvbSAnLi90b2xsZS1jb25maWcnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFRoZW1lU2VydmljZSB7XG4gIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMjtcbiAgcHJpdmF0ZSBpc0RhcmtTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG4gIGlzRGFyayQgPSB0aGlzLmlzRGFya1N1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBPYmplY3QsXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChUT0xMRV9DT05GSUcpIHByaXZhdGUgY29uZmlnOiBUb2xsZUNvbmZpZyxcbiAgICByZW5kZXJlckZhY3Rvcnk6IFJlbmRlcmVyRmFjdG9yeTJcbiAgKSB7XG4gICAgdGhpcy5yZW5kZXJlciA9IHJlbmRlcmVyRmFjdG9yeS5jcmVhdGVSZW5kZXJlcihudWxsLCBudWxsKTtcbiAgICB0aGlzLmluaXRpYWxpemVUaGVtZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0aWFsaXplVGhlbWUoKSB7XG4gICAgaWYgKCFpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSByZXR1cm47XG5cbiAgICAvLyAxLiBEZXRlcm1pbmUgSW5pdGlhbCBNb2RlIChEYXJrL0xpZ2h0KVxuICAgIGNvbnN0IHNhdmVkVGhlbWUgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgndG9sbGUtdGhlbWUnKTtcbiAgICBjb25zdCBwcmVmZXJzRGFyayA9IHdpbmRvdy5tYXRjaE1lZGlhKCcocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspJykubWF0Y2hlcztcblxuICAgIC8vIFByaW9yaXR5OiBTYXZlZCBQcmVmZXJlbmNlID4gQ29uZmlnIERlZmF1bHQgPiBTeXN0ZW0gUHJlZmVyZW5jZVxuICAgIGNvbnN0IHNob3VsZEJlRGFyayA9IHNhdmVkVGhlbWVcbiAgICAgID8gc2F2ZWRUaGVtZSA9PT0gJ2RhcmsnXG4gICAgICA6ICh0aGlzLmNvbmZpZz8uZGFya0J5RGVmYXVsdCA/PyBwcmVmZXJzRGFyayk7XG5cbiAgICBpZiAoc2hvdWxkQmVEYXJrKSB7XG4gICAgICB0aGlzLmVuYWJsZURhcmtNb2RlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGlzYWJsZURhcmtNb2RlKCk7XG4gICAgfVxuXG4gICAgLy8gMi4gQXBwbHkgQnJhbmQgQ29uZmlnIChDb2xvcnMvUmFkaXVzKVxuICAgIGlmICh0aGlzLmNvbmZpZykge1xuICAgICAgdGhpcy5hcHBseUJyYW5kQ29uZmlnKHRoaXMuY29uZmlnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFwcGx5QnJhbmRDb25maWcoY29uZmlnOiBUb2xsZUNvbmZpZykge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICBpZiAoY29uZmlnLnByaW1hcnlDb2xvcikge1xuICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShyb290LCAnLS1wcmltYXJ5JywgY29uZmlnLnByaW1hcnlDb2xvcik7XG4gICAgfVxuICAgIGlmIChjb25maWcucmFkaXVzKSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHJvb3QsICctLXJhZGl1cycsIGNvbmZpZy5yYWRpdXMpO1xuICAgIH1cbiAgfVxuXG4gIHRvZ2dsZVRoZW1lKCkge1xuICAgIGNvbnN0IGlzRGFyayA9IHRoaXMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygnZGFyaycpO1xuICAgIGlzRGFyayA/IHRoaXMuZGlzYWJsZURhcmtNb2RlKCkgOiB0aGlzLmVuYWJsZURhcmtNb2RlKCk7XG4gIH1cblxuICBwcml2YXRlIGVuYWJsZURhcmtNb2RlKCkge1xuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICdkYXJrJyk7XG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3RvbGxlLXRoZW1lJywgJ2RhcmsnKTtcbiAgICB0aGlzLmlzRGFya1N1YmplY3QubmV4dCh0cnVlKTtcbiAgfVxuXG4gIHByaXZhdGUgZGlzYWJsZURhcmtNb2RlKCkge1xuICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICdkYXJrJyk7XG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3RvbGxlLXRoZW1lJywgJ2xpZ2h0Jyk7XG4gICAgdGhpcy5pc0RhcmtTdWJqZWN0Lm5leHQoZmFsc2UpO1xuICB9XG59XG4iXX0=
@@ -1,11 +1,15 @@
1
- import { InjectionToken } from '@angular/core';
1
+ import { APP_INITIALIZER, InjectionToken } from '@angular/core';
2
+ import { ThemeService } from './theme.service';
2
3
  export const TOLLE_CONFIG = new InjectionToken('TolleConfig');
3
4
  export function provideTolleConfig(config) {
4
5
  return [
6
+ { provide: TOLLE_CONFIG, useValue: config },
5
7
  {
6
- provide: TOLLE_CONFIG,
7
- useValue: config
8
+ provide: APP_INITIALIZER,
9
+ useFactory: (themeService) => () => themeService, // Just force injection
10
+ deps: [ThemeService],
11
+ multi: true
8
12
  }
9
13
  ];
10
14
  }
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9sbGUtY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9sbGUvc3JjL2xpYi90b2xsZS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBWSxNQUFNLGVBQWUsQ0FBQztBQVN6RCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxjQUFjLENBQWMsYUFBYSxDQUFDLENBQUM7QUFFM0UsTUFBTSxVQUFVLGtCQUFrQixDQUFDLE1BQW1CO0lBQ3BELE9BQU87UUFDTDtZQUNFLE9BQU8sRUFBRSxZQUFZO1lBQ3JCLFFBQVEsRUFBRSxNQUFNO1NBQ2pCO0tBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3Rpb25Ub2tlbiwgUHJvdmlkZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGludGVyZmFjZSBUb2xsZUNvbmZpZyB7XG4gIHByaW1hcnlDb2xvcj86IHN0cmluZztcbiAgcmFkaXVzPzogc3RyaW5nO1xuICBkZWZhdWx0VG9hc3REdXJhdGlvbj86IG51bWJlcjtcbiAgZGFya0J5RGVmYXVsdD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjb25zdCBUT0xMRV9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48VG9sbGVDb25maWc+KCdUb2xsZUNvbmZpZycpO1xuXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZVRvbGxlQ29uZmlnKGNvbmZpZzogVG9sbGVDb25maWcpOiBQcm92aWRlcltdIHtcbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBUT0xMRV9DT05GSUcsXG4gICAgICB1c2VWYWx1ZTogY29uZmlnXG4gICAgfVxuICBdO1xufVxuIl19
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9sbGUtY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9sbGUvc3JjL2xpYi90b2xsZS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLGVBQWUsRUFBRSxjQUFjLEVBQVcsTUFBTSxlQUFlLENBQUM7QUFDeEUsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBUzdDLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxJQUFJLGNBQWMsQ0FBYyxhQUFhLENBQUMsQ0FBQztBQUUzRSxNQUFNLFVBQVUsa0JBQWtCLENBQUMsTUFBbUI7SUFDcEQsT0FBTztRQUNMLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFO1FBQzNDO1lBQ0UsT0FBTyxFQUFFLGVBQWU7WUFDeEIsVUFBVSxFQUFFLENBQUMsWUFBMEIsRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsWUFBWSxFQUFFLHVCQUF1QjtZQUN2RixJQUFJLEVBQUUsQ0FBQyxZQUFZLENBQUM7WUFDcEIsS0FBSyxFQUFFLElBQUk7U0FDWjtLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtBUFBfSU5JVElBTElaRVIsIEluamVjdGlvblRva2VuLCBQcm92aWRlcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1RoZW1lU2VydmljZX0gZnJvbSAnLi90aGVtZS5zZXJ2aWNlJztcblxuZXhwb3J0IGludGVyZmFjZSBUb2xsZUNvbmZpZyB7XG4gIHByaW1hcnlDb2xvcj86IHN0cmluZztcbiAgcmFkaXVzPzogc3RyaW5nO1xuICBkZWZhdWx0VG9hc3REdXJhdGlvbj86IG51bWJlcjtcbiAgZGFya0J5RGVmYXVsdD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjb25zdCBUT0xMRV9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48VG9sbGVDb25maWc+KCdUb2xsZUNvbmZpZycpO1xuXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZVRvbGxlQ29uZmlnKGNvbmZpZzogVG9sbGVDb25maWcpOiBQcm92aWRlcltdIHtcbiAgcmV0dXJuIFtcbiAgICB7IHByb3ZpZGU6IFRPTExFX0NPTkZJRywgdXNlVmFsdWU6IGNvbmZpZyB9LFxuICAgIHtcbiAgICAgIHByb3ZpZGU6IEFQUF9JTklUSUFMSVpFUixcbiAgICAgIHVzZUZhY3Rvcnk6ICh0aGVtZVNlcnZpY2U6IFRoZW1lU2VydmljZSkgPT4gKCkgPT4gdGhlbWVTZXJ2aWNlLCAvLyBKdXN0IGZvcmNlIGluamVjdGlvblxuICAgICAgZGVwczogW1RoZW1lU2VydmljZV0sXG4gICAgICBtdWx0aTogdHJ1ZVxuICAgIH1cbiAgXTtcbn1cbiJdfQ==
@@ -1,14 +1,14 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  import * as i0 from '@angular/core';
4
- import { Component, Input, forwardRef, Injectable, Optional, HostListener, ViewChild, ContentChildren, EventEmitter, Output, Directive, InjectionToken, inject, ChangeDetectorRef, ChangeDetectionStrategy, TemplateRef, Injector } from '@angular/core';
4
+ import { Component, Input, forwardRef, Injectable, Optional, HostListener, ViewChild, ContentChildren, EventEmitter, Output, Directive, PLATFORM_ID, Inject, InjectionToken, APP_INITIALIZER, inject, ChangeDetectorRef, ChangeDetectionStrategy, TemplateRef, Injector } from '@angular/core';
5
5
  import * as i1 from '@angular/common';
6
- import { CommonModule } from '@angular/common';
6
+ import { CommonModule, isPlatformBrowser, DOCUMENT } from '@angular/common';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import * as i2 from '@angular/forms';
9
9
  import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
10
10
  import { autoUpdate, computePosition, offset, flip, shift } from '@floating-ui/dom';
11
- import { Subject, Subscription } from 'rxjs';
11
+ import { Subject, Subscription, BehaviorSubject } from 'rxjs';
12
12
  import { startOfWeek, startOfMonth, endOfWeek, endOfMonth, eachDayOfInterval, subMonths, subYears, addMonths, addYears, isSameMonth, setMonth, setYear, isSameDay, isToday, isBefore, startOfDay, parse, isValid, format, isWithinInterval } from 'date-fns';
13
13
  import * as i1$1 from '@angular/cdk/overlay';
14
14
  import { OverlayConfig } from '@angular/cdk/overlay';
@@ -1137,12 +1137,92 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1137
1137
  args: [{ providedIn: 'root' }]
1138
1138
  }], ctorParameters: () => [] });
1139
1139
 
1140
+ class ThemeService {
1141
+ document;
1142
+ platformId;
1143
+ config;
1144
+ renderer;
1145
+ isDarkSubject = new BehaviorSubject(false);
1146
+ isDark$ = this.isDarkSubject.asObservable();
1147
+ constructor(document, platformId, config, rendererFactory) {
1148
+ this.document = document;
1149
+ this.platformId = platformId;
1150
+ this.config = config;
1151
+ this.renderer = rendererFactory.createRenderer(null, null);
1152
+ this.initializeTheme();
1153
+ }
1154
+ initializeTheme() {
1155
+ if (!isPlatformBrowser(this.platformId))
1156
+ return;
1157
+ // 1. Determine Initial Mode (Dark/Light)
1158
+ const savedTheme = localStorage.getItem('tolle-theme');
1159
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
1160
+ // Priority: Saved Preference > Config Default > System Preference
1161
+ const shouldBeDark = savedTheme
1162
+ ? savedTheme === 'dark'
1163
+ : (this.config?.darkByDefault ?? prefersDark);
1164
+ if (shouldBeDark) {
1165
+ this.enableDarkMode();
1166
+ }
1167
+ else {
1168
+ this.disableDarkMode();
1169
+ }
1170
+ // 2. Apply Brand Config (Colors/Radius)
1171
+ if (this.config) {
1172
+ this.applyBrandConfig(this.config);
1173
+ }
1174
+ }
1175
+ applyBrandConfig(config) {
1176
+ const root = this.document.documentElement;
1177
+ if (config.primaryColor) {
1178
+ this.renderer.setStyle(root, '--primary', config.primaryColor);
1179
+ }
1180
+ if (config.radius) {
1181
+ this.renderer.setStyle(root, '--radius', config.radius);
1182
+ }
1183
+ }
1184
+ toggleTheme() {
1185
+ const isDark = this.document.documentElement.classList.contains('dark');
1186
+ isDark ? this.disableDarkMode() : this.enableDarkMode();
1187
+ }
1188
+ enableDarkMode() {
1189
+ this.renderer.addClass(this.document.documentElement, 'dark');
1190
+ localStorage.setItem('tolle-theme', 'dark');
1191
+ this.isDarkSubject.next(true);
1192
+ }
1193
+ disableDarkMode() {
1194
+ this.renderer.removeClass(this.document.documentElement, 'dark');
1195
+ localStorage.setItem('tolle-theme', 'light');
1196
+ this.isDarkSubject.next(false);
1197
+ }
1198
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: TOLLE_CONFIG, optional: true }, { token: i0.RendererFactory2 }], target: i0.ɵɵFactoryTarget.Injectable });
1199
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, providedIn: 'root' });
1200
+ }
1201
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, decorators: [{
1202
+ type: Injectable,
1203
+ args: [{ providedIn: 'root' }]
1204
+ }], ctorParameters: () => [{ type: Document, decorators: [{
1205
+ type: Inject,
1206
+ args: [DOCUMENT]
1207
+ }] }, { type: Object, decorators: [{
1208
+ type: Inject,
1209
+ args: [PLATFORM_ID]
1210
+ }] }, { type: undefined, decorators: [{
1211
+ type: Optional
1212
+ }, {
1213
+ type: Inject,
1214
+ args: [TOLLE_CONFIG]
1215
+ }] }, { type: i0.RendererFactory2 }] });
1216
+
1140
1217
  const TOLLE_CONFIG = new InjectionToken('TolleConfig');
1141
1218
  function provideTolleConfig(config) {
1142
1219
  return [
1220
+ { provide: TOLLE_CONFIG, useValue: config },
1143
1221
  {
1144
- provide: TOLLE_CONFIG,
1145
- useValue: config
1222
+ provide: APP_INITIALIZER,
1223
+ useFactory: (themeService) => () => themeService, // Just force injection
1224
+ deps: [ThemeService],
1225
+ multi: true
1146
1226
  }
1147
1227
  ];
1148
1228
  }