|
1 | | -import { |
2 | | - forwardRef, |
3 | | - inject, |
4 | | - Injectable, |
5 | | - Injector, |
6 | | - ProviderToken, |
7 | | -} from '@angular/core'; |
| 1 | +import { inject, Injectable, Injector } from '@angular/core'; |
8 | 2 |
|
9 | | -import { ThemeBuilder } from './builder'; |
| 3 | +import { ThemeBuilderComposition } from './builder-composition'; |
10 | 4 | import { ThemeTokenRegistry, ThemeTokens } from './token'; |
11 | 5 |
|
12 | | -@Injectable({ |
13 | | - providedIn: 'root', |
14 | | - useExisting: forwardRef(() => SimpleThemeManager), |
15 | | -}) |
16 | | -export abstract class ThemeManager { |
17 | | - abstract buildAndApply<Builders extends ThemeBuilderMap>( |
18 | | - builders: Builders, |
19 | | - configs: ThemeBuilderConfigMapOf<Builders>, |
20 | | - ): void; |
21 | | - abstract build<Builders extends ThemeBuilderMap>( |
22 | | - builders: Builders, |
23 | | - configs: ThemeBuilderConfigMapOf<Builders>, |
24 | | - ): ThemeTokens; |
25 | | - abstract apply(tokens: ThemeTokens): void; |
26 | | -} |
27 | | - |
28 | | -export interface ThemeBuilderMap { |
29 | | - [name: string]: ProviderToken<ThemeBuilder<unknown>>; |
30 | | -} |
31 | | - |
32 | | -export type ThemeBuilderConfigMapOf<Builders extends ThemeBuilderMap> = { |
33 | | - [Name in keyof Builders]: Builders[Name] extends ProviderToken< |
34 | | - ThemeBuilder<infer Config> |
35 | | - > |
36 | | - ? Config |
37 | | - : never; |
38 | | -}; |
39 | | - |
40 | 6 | @Injectable({ providedIn: 'root' }) |
41 | | -export class SimpleThemeManager implements ThemeManager { |
| 7 | +export class ThemeManager { |
42 | 8 | protected injector = inject(Injector); |
43 | 9 | protected tokens = inject(ThemeTokenRegistry); |
44 | 10 |
|
45 | | - buildAndApply<Builders extends ThemeBuilderMap>( |
46 | | - builders: Builders, |
47 | | - configs: ThemeBuilderConfigMapOf<Builders>, |
48 | | - ): void { |
49 | | - const tokens = this.build(builders, configs); |
50 | | - this.apply(tokens); |
51 | | - } |
52 | | - |
53 | | - build<Builders extends ThemeBuilderMap>( |
54 | | - builders: Builders, |
55 | | - configs: ThemeBuilderConfigMapOf<Builders>, |
56 | | - ): ThemeTokens { |
57 | | - return Object.entries(builders).reduce( |
58 | | - (tokens, [name, builder]) => ({ |
59 | | - ...tokens, |
60 | | - ...this.injector.get(builder).build({ name, config: configs[name] }), |
61 | | - }), |
62 | | - {}, |
63 | | - ); |
| 11 | + build(config: ThemeBuildConfig): ThemeTokens { |
| 12 | + const tokens: ThemeTokens = {}; |
| 13 | + for (const [name, composition] of Object.entries(config)) { |
| 14 | + const { builder: token, config } = composition; |
| 15 | + const builder = this.injector.get(token); |
| 16 | + const result = builder.build({ name, config }); |
| 17 | + Object.assign(tokens, result); |
| 18 | + } |
| 19 | + return tokens; |
64 | 20 | } |
65 | 21 |
|
66 | 22 | apply(tokens: ThemeTokens): void { |
67 | 23 | for (const name in tokens) this.tokens.set(name, tokens[name]); |
68 | 24 | } |
| 25 | + |
| 26 | + buildAndApply(config: ThemeBuildConfig): void { |
| 27 | + const tokens = this.build(config); |
| 28 | + this.apply(tokens); |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +export interface ThemeBuildConfig { |
| 33 | + [name: string]: ThemeBuilderComposition; |
69 | 34 | } |
0 commit comments