@tolle_/tolle-ui 0.0.4-beta → 0.0.6-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.
|
@@ -22,23 +22,29 @@ export class ThemeService {
|
|
|
22
22
|
return;
|
|
23
23
|
// 1. Determine Initial Mode (Dark/Light)
|
|
24
24
|
const savedTheme = localStorage.getItem('tolle-theme');
|
|
25
|
-
const
|
|
26
|
-
//
|
|
25
|
+
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
26
|
+
// Logic: Saved Preference > Config Default > System Preference
|
|
27
27
|
const shouldBeDark = savedTheme
|
|
28
28
|
? savedTheme === 'dark'
|
|
29
|
-
: (this.config?.darkByDefault ??
|
|
29
|
+
: (this.config?.darkByDefault ?? systemPrefersDark);
|
|
30
30
|
if (shouldBeDark) {
|
|
31
31
|
this.enableDarkMode();
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
34
|
this.disableDarkMode();
|
|
35
35
|
}
|
|
36
|
-
// 2. Apply Brand Config
|
|
36
|
+
// 2. Apply Brand Config
|
|
37
37
|
if (this.config) {
|
|
38
38
|
this.applyBrandConfig(this.config);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Applies the brand identity variables.
|
|
43
|
+
* These are applied to :root (html) so they ripple through all color-mix functions.
|
|
44
|
+
*/
|
|
41
45
|
applyBrandConfig(config) {
|
|
46
|
+
if (!isPlatformBrowser(this.platformId))
|
|
47
|
+
return;
|
|
42
48
|
const root = this.document.documentElement;
|
|
43
49
|
if (config.primaryColor) {
|
|
44
50
|
this.renderer.setStyle(root, '--primary', config.primaryColor);
|
|
@@ -48,8 +54,8 @@ export class ThemeService {
|
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
toggleTheme() {
|
|
51
|
-
const
|
|
52
|
-
|
|
57
|
+
const isCurrentlyDark = this.document.documentElement.classList.contains('dark');
|
|
58
|
+
isCurrentlyDark ? this.disableDarkMode() : this.enableDarkMode();
|
|
53
59
|
}
|
|
54
60
|
enableDarkMode() {
|
|
55
61
|
this.renderer.addClass(this.document.documentElement, 'dark');
|
|
@@ -61,6 +67,12 @@ export class ThemeService {
|
|
|
61
67
|
localStorage.setItem('tolle-theme', 'light');
|
|
62
68
|
this.isDarkSubject.next(false);
|
|
63
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Helper to get current state for components that might need JS-based logic
|
|
72
|
+
*/
|
|
73
|
+
get currentTheme() {
|
|
74
|
+
return this.isDarkSubject.value ? 'dark' : 'light';
|
|
75
|
+
}
|
|
64
76
|
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
77
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, providedIn: 'root' });
|
|
66
78
|
}
|
|
@@ -79,4 +91,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
79
91
|
type: Inject,
|
|
80
92
|
args: [TOLLE_CONFIG]
|
|
81
93
|
}] }, { type: i0.RendererFactory2 }] });
|
|
82
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
94
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhlbWUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvdGhlbWUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUErQixNQUFNLGVBQWUsQ0FBQztBQUN2RyxPQUFPLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN2QyxPQUFPLEVBQUUsWUFBWSxFQUFlLE1BQU0sZ0JBQWdCLENBQUM7O0FBRzNELE1BQU0sT0FBTyxZQUFZO0lBTUs7SUFDRztJQUNhO0lBUHBDLFFBQVEsQ0FBWTtJQUNwQixhQUFhLEdBQUcsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7SUFDNUQsT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLENBQUM7SUFFNUMsWUFDNEIsUUFBa0IsRUFDZixVQUFrQixFQUNMLE1BQW1CLEVBQzdELGVBQWlDO1FBSFAsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNmLGVBQVUsR0FBVixVQUFVLENBQVE7UUFDTCxXQUFNLEdBQU4sTUFBTSxDQUFhO1FBRzdELElBQUksQ0FBQyxRQUFRLEdBQUcsZUFBZSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDM0QsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFTyxlQUFlO1FBQ3JCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO1lBQUUsT0FBTztRQUVoRCx5Q0FBeUM7UUFDekMsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN2RCxNQUFNLGlCQUFpQixH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IEluamVjdCwgUExBVEZPUk1fSUQsIE9wdGlvbmFsLCBSZW5kZXJlcjIsIFJlbmRlcmVyRmFjdG9yeTIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERPQ1VNRU5ULCBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFRPTExFX0NPTkZJRywgVG9sbGVDb25maWcgfSBmcm9tICcuL3RvbGxlLWNvbmZpZyc7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgVGhlbWVTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyO1xuICBwcml2YXRlIGlzRGFya1N1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgaXNEYXJrJCA9IHRoaXMuaXNEYXJrU3ViamVjdC5hc09ic2VydmFibGUoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIGRvY3VtZW50OiBEb2N1bWVudCxcbiAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ6IE9iamVjdCxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KFRPTExFX0NPTkZJRykgcHJpdmF0ZSBjb25maWc6IFRvbGxlQ29uZmlnLFxuICAgIHJlbmRlcmVyRmFjdG9yeTogUmVuZGVyZXJGYWN0b3J5MlxuICApIHtcbiAgICB0aGlzLnJlbmRlcmVyID0gcmVuZGVyZXJGYWN0b3J5LmNyZWF0ZVJlbmRlcmVyKG51bGwsIG51bGwpO1xuICAgIHRoaXMuaW5pdGlhbGl6ZVRoZW1lKCk7XG4gIH1cblxuICBwcml2YXRlIGluaXRpYWxpemVUaGVtZSgpIHtcbiAgICBpZiAoIWlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkpIHJldHVybjtcblxuICAgIC8vIDEuIERldGVybWluZSBJbml0aWFsIE1vZGUgKERhcmsvTGlnaHQpXG4gICAgY29uc3Qgc2F2ZWRUaGVtZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd0b2xsZS10aGVtZScpO1xuICAgIGNvbnN0IHN5c3RlbVByZWZlcnNEYXJrID0gd2luZG93Lm1hdGNoTWVkaWEoJyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyayknKS5tYXRjaGVzO1xuXG4gICAgLy8gTG9naWM6IFNhdmVkIFByZWZlcmVuY2UgPiBDb25maWcgRGVmYXVsdCA+IFN5c3RlbSBQcmVmZXJlbmNlXG4gICAgY29uc3Qgc2hvdWxkQmVEYXJrID0gc2F2ZWRUaGVtZVxuICAgICAgPyBzYXZlZFRoZW1lID09PSAnZGFyaydcbiAgICAgIDogKHRoaXMuY29uZmlnPy5kYXJrQnlEZWZhdWx0ID8/IHN5c3RlbVByZWZlcnNEYXJrKTtcblxuICAgIGlmIChzaG91bGRCZURhcmspIHtcbiAgICAgIHRoaXMuZW5hYmxlRGFya01vZGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kaXNhYmxlRGFya01vZGUoKTtcbiAgICB9XG5cbiAgICAvLyAyLiBBcHBseSBCcmFuZCBDb25maWdcbiAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgIHRoaXMuYXBwbHlCcmFuZENvbmZpZyh0aGlzLmNvbmZpZyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgdGhlIGJyYW5kIGlkZW50aXR5IHZhcmlhYmxlcy5cbiAgICogVGhlc2UgYXJlIGFwcGxpZWQgdG8gOnJvb3QgKGh0bWwpIHNvIHRoZXkgcmlwcGxlIHRocm91Z2ggYWxsIGNvbG9yLW1peCBmdW5jdGlvbnMuXG4gICAqL1xuICBhcHBseUJyYW5kQ29uZmlnKGNvbmZpZzogVG9sbGVDb25maWcpIHtcbiAgICBpZiAoIWlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkpIHJldHVybjtcblxuICAgIGNvbnN0IHJvb3QgPSB0aGlzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuICAgIGlmIChjb25maWcucHJpbWFyeUNvbG9yKSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHJvb3QsICctLXByaW1hcnknLCBjb25maWcucHJpbWFyeUNvbG9yKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLnJhZGl1cykge1xuICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShyb290LCAnLS1yYWRpdXMnLCBjb25maWcucmFkaXVzKTtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVUaGVtZSgpIHtcbiAgICBjb25zdCBpc0N1cnJlbnRseURhcmsgPSB0aGlzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ2RhcmsnKTtcbiAgICBpc0N1cnJlbnRseURhcmsgPyB0aGlzLmRpc2FibGVEYXJrTW9kZSgpIDogdGhpcy5lbmFibGVEYXJrTW9kZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbmFibGVEYXJrTW9kZSgpIHtcbiAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCAnZGFyaycpO1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCd0b2xsZS10aGVtZScsICdkYXJrJyk7XG4gICAgdGhpcy5pc0RhcmtTdWJqZWN0Lm5leHQodHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIGRpc2FibGVEYXJrTW9kZSgpIHtcbiAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCAnZGFyaycpO1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCd0b2xsZS10aGVtZScsICdsaWdodCcpO1xuICAgIHRoaXMuaXNEYXJrU3ViamVjdC5uZXh0KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgdG8gZ2V0IGN1cnJlbnQgc3RhdGUgZm9yIGNvbXBvbmVudHMgdGhhdCBtaWdodCBuZWVkIEpTLWJhc2VkIGxvZ2ljXG4gICAqL1xuICBnZXQgY3VycmVudFRoZW1lKCk6ICdkYXJrJyB8ICdsaWdodCcge1xuICAgIHJldHVybiB0aGlzLmlzRGFya1N1YmplY3QudmFsdWUgPyAnZGFyaycgOiAnbGlnaHQnO1xuICB9XG59XG4iXX0=
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { APP_INITIALIZER, InjectionToken } from '@angular/core';
|
|
2
2
|
import { ThemeService } from './theme.service';
|
|
3
3
|
export const TOLLE_CONFIG = new InjectionToken('TolleConfig');
|
|
4
|
+
// projects/tolle/src/lib/tolle-config.ts
|
|
4
5
|
export function provideTolleConfig(config) {
|
|
5
6
|
return [
|
|
6
7
|
{ provide: TOLLE_CONFIG, useValue: config },
|
|
7
8
|
{
|
|
8
9
|
provide: APP_INITIALIZER,
|
|
9
|
-
useFactory: (themeService) => () =>
|
|
10
|
+
useFactory: (themeService) => () => {
|
|
11
|
+
// This is an empty execution that triggers the Service Constructor
|
|
12
|
+
// ensuring initialization happens during the Angular bootstrap phase.
|
|
13
|
+
},
|
|
10
14
|
deps: [ThemeService],
|
|
11
|
-
multi: true
|
|
12
|
-
}
|
|
15
|
+
multi: true,
|
|
16
|
+
},
|
|
13
17
|
];
|
|
14
18
|
}
|
|
15
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9sbGUtY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9sbGUvc3JjL2xpYi90b2xsZS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLGVBQWUsRUFBRSxjQUFjLEVBQVcsTUFBTSxlQUFlLENBQUM7QUFDeEUsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBUzdDLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxJQUFJLGNBQWMsQ0FBYyxhQUFhLENBQUMsQ0FBQztBQUUzRSx5Q0FBeUM7QUFDekMsTUFBTSxVQUFVLGtCQUFrQixDQUFDLE1BQW1CO0lBQ3BELE9BQU87UUFDTCxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRTtRQUMzQztZQUNFLE9BQU8sRUFBRSxlQUFlO1lBQ3hCLFVBQVUsRUFBRSxDQUFDLFlBQTBCLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRTtnQkFDL0MsbUVBQW1FO2dCQUNuRSxzRUFBc0U7WUFDeEUsQ0FBQztZQUNELElBQUksRUFBRSxDQUFDLFlBQVksQ0FBQztZQUNwQixLQUFLLEVBQUUsSUFBSTtTQUNaO0tBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0FQUF9JTklUSUFMSVpFUiwgSW5qZWN0aW9uVG9rZW4sIFByb3ZpZGVyfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7VGhlbWVTZXJ2aWNlfSBmcm9tICcuL3RoZW1lLnNlcnZpY2UnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRvbGxlQ29uZmlnIHtcbiAgcHJpbWFyeUNvbG9yPzogc3RyaW5nO1xuICByYWRpdXM/OiBzdHJpbmc7XG4gIGRlZmF1bHRUb2FzdER1cmF0aW9uPzogbnVtYmVyO1xuICBkYXJrQnlEZWZhdWx0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IFRPTExFX0NPTkZJRyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxUb2xsZUNvbmZpZz4oJ1RvbGxlQ29uZmlnJyk7XG5cbi8vIHByb2plY3RzL3RvbGxlL3NyYy9saWIvdG9sbGUtY29uZmlnLnRzXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZVRvbGxlQ29uZmlnKGNvbmZpZzogVG9sbGVDb25maWcpOiBQcm92aWRlcltdIHtcbiAgcmV0dXJuIFtcbiAgICB7IHByb3ZpZGU6IFRPTExFX0NPTkZJRywgdXNlVmFsdWU6IGNvbmZpZyB9LFxuICAgIHtcbiAgICAgIHByb3ZpZGU6IEFQUF9JTklUSUFMSVpFUixcbiAgICAgIHVzZUZhY3Rvcnk6ICh0aGVtZVNlcnZpY2U6IFRoZW1lU2VydmljZSkgPT4gKCkgPT4ge1xuICAgICAgICAvLyBUaGlzIGlzIGFuIGVtcHR5IGV4ZWN1dGlvbiB0aGF0IHRyaWdnZXJzIHRoZSBTZXJ2aWNlIENvbnN0cnVjdG9yXG4gICAgICAgIC8vIGVuc3VyaW5nIGluaXRpYWxpemF0aW9uIGhhcHBlbnMgZHVyaW5nIHRoZSBBbmd1bGFyIGJvb3RzdHJhcCBwaGFzZS5cbiAgICAgIH0sXG4gICAgICBkZXBzOiBbVGhlbWVTZXJ2aWNlXSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gIF07XG59XG4iXX0=
|
|
@@ -1156,23 +1156,29 @@ class ThemeService {
|
|
|
1156
1156
|
return;
|
|
1157
1157
|
// 1. Determine Initial Mode (Dark/Light)
|
|
1158
1158
|
const savedTheme = localStorage.getItem('tolle-theme');
|
|
1159
|
-
const
|
|
1160
|
-
//
|
|
1159
|
+
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
1160
|
+
// Logic: Saved Preference > Config Default > System Preference
|
|
1161
1161
|
const shouldBeDark = savedTheme
|
|
1162
1162
|
? savedTheme === 'dark'
|
|
1163
|
-
: (this.config?.darkByDefault ??
|
|
1163
|
+
: (this.config?.darkByDefault ?? systemPrefersDark);
|
|
1164
1164
|
if (shouldBeDark) {
|
|
1165
1165
|
this.enableDarkMode();
|
|
1166
1166
|
}
|
|
1167
1167
|
else {
|
|
1168
1168
|
this.disableDarkMode();
|
|
1169
1169
|
}
|
|
1170
|
-
// 2. Apply Brand Config
|
|
1170
|
+
// 2. Apply Brand Config
|
|
1171
1171
|
if (this.config) {
|
|
1172
1172
|
this.applyBrandConfig(this.config);
|
|
1173
1173
|
}
|
|
1174
1174
|
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Applies the brand identity variables.
|
|
1177
|
+
* These are applied to :root (html) so they ripple through all color-mix functions.
|
|
1178
|
+
*/
|
|
1175
1179
|
applyBrandConfig(config) {
|
|
1180
|
+
if (!isPlatformBrowser(this.platformId))
|
|
1181
|
+
return;
|
|
1176
1182
|
const root = this.document.documentElement;
|
|
1177
1183
|
if (config.primaryColor) {
|
|
1178
1184
|
this.renderer.setStyle(root, '--primary', config.primaryColor);
|
|
@@ -1182,8 +1188,8 @@ class ThemeService {
|
|
|
1182
1188
|
}
|
|
1183
1189
|
}
|
|
1184
1190
|
toggleTheme() {
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1191
|
+
const isCurrentlyDark = this.document.documentElement.classList.contains('dark');
|
|
1192
|
+
isCurrentlyDark ? this.disableDarkMode() : this.enableDarkMode();
|
|
1187
1193
|
}
|
|
1188
1194
|
enableDarkMode() {
|
|
1189
1195
|
this.renderer.addClass(this.document.documentElement, 'dark');
|
|
@@ -1195,6 +1201,12 @@ class ThemeService {
|
|
|
1195
1201
|
localStorage.setItem('tolle-theme', 'light');
|
|
1196
1202
|
this.isDarkSubject.next(false);
|
|
1197
1203
|
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Helper to get current state for components that might need JS-based logic
|
|
1206
|
+
*/
|
|
1207
|
+
get currentTheme() {
|
|
1208
|
+
return this.isDarkSubject.value ? 'dark' : 'light';
|
|
1209
|
+
}
|
|
1198
1210
|
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
1211
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, providedIn: 'root' });
|
|
1200
1212
|
}
|
|
@@ -1215,15 +1227,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1215
1227
|
}] }, { type: i0.RendererFactory2 }] });
|
|
1216
1228
|
|
|
1217
1229
|
const TOLLE_CONFIG = new InjectionToken('TolleConfig');
|
|
1230
|
+
// projects/tolle/src/lib/tolle-config.ts
|
|
1218
1231
|
function provideTolleConfig(config) {
|
|
1219
1232
|
return [
|
|
1220
1233
|
{ provide: TOLLE_CONFIG, useValue: config },
|
|
1221
1234
|
{
|
|
1222
1235
|
provide: APP_INITIALIZER,
|
|
1223
|
-
useFactory: (themeService) => () =>
|
|
1236
|
+
useFactory: (themeService) => () => {
|
|
1237
|
+
// This is an empty execution that triggers the Service Constructor
|
|
1238
|
+
// ensuring initialization happens during the Angular bootstrap phase.
|
|
1239
|
+
},
|
|
1224
1240
|
deps: [ThemeService],
|
|
1225
|
-
multi: true
|
|
1226
|
-
}
|
|
1241
|
+
multi: true,
|
|
1242
|
+
},
|
|
1227
1243
|
];
|
|
1228
1244
|
}
|
|
1229
1245
|
|