@udixio/theme 1.0.0-beta.7 → 1.0.0-beta.9
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.
- package/dist/app.service.d.ts +6 -3
- package/dist/color/color.interface.d.ts +1 -2
- package/dist/color/entities/color.entity.d.ts +6 -1
- package/dist/color/index.d.ts +1 -2
- package/dist/color/models/default-color.model.d.ts +2 -3
- package/dist/color/services/color-manager.service.d.ts +18 -0
- package/dist/color/services/color.service.d.ts +21 -0
- package/dist/color/services/index.d.ts +2 -0
- package/dist/config/config.interface.d.ts +13 -0
- package/dist/config/config.module.d.ts +2 -0
- package/dist/config/config.service.d.ts +12 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/main.d.ts +2 -1
- package/dist/plugin/plugin.abstract.d.ts +6 -0
- package/dist/plugin/plugin.module.d.ts +2 -0
- package/dist/plugin/plugin.service.d.ts +10 -0
- package/dist/plugins/tailwind/Tailwind.plugin.d.ts +14 -0
- package/dist/plugins/tailwind/main.d.ts +10 -0
- package/dist/plugins/tailwind/plugins-tailwind/state.d.ts +4 -0
- package/dist/plugins/tailwind/plugins-tailwind/themer.d.ts +4 -0
- package/dist/theme/entities/variant.entity.d.ts +2 -1
- package/dist/theme/services/scheme.service.d.ts +7 -2
- package/dist/theme/services/theme.service.d.ts +10 -4
- package/dist/theme/services/variant.service.d.ts +4 -0
- package/dist/theme.cjs.development.js +1081 -506
- package/dist/theme.cjs.development.js.map +1 -1
- package/dist/theme.cjs.production.min.js +1 -1
- package/dist/theme.cjs.production.min.js.map +1 -1
- package/dist/theme.esm.js +1079 -507
- package/dist/theme.esm.js.map +1 -1
- package/package.json +4 -3
- package/src/app.container.ts +9 -1
- package/src/app.service.ts +8 -2
- package/src/color/color.interface.ts +1 -3
- package/src/color/color.module.ts +2 -2
- package/src/color/entities/color.entity.ts +13 -1
- package/src/color/index.ts +1 -2
- package/src/color/models/default-color.model.ts +205 -202
- package/src/color/{color-manager.service.ts → services/color-manager.service.ts} +17 -10
- package/src/color/{color.service.spec.ts → services/color.service.spec.ts} +1 -1
- package/src/color/{color.service.ts → services/color.service.ts} +33 -21
- package/src/color/services/index.ts +2 -0
- package/src/config/config.interface.ts +14 -0
- package/src/config/config.module.ts +7 -0
- package/src/config/config.service.ts +74 -0
- package/src/config/index.ts +2 -0
- package/src/index.ts +1 -0
- package/src/main.ts +9 -1
- package/src/plugin/plugin.abstract.ts +8 -0
- package/src/plugin/plugin.module.ts +7 -0
- package/src/plugin/plugin.service.ts +30 -0
- package/src/plugins/tailwind/Tailwind.plugin.ts +53 -0
- package/src/plugins/tailwind/main.ts +18 -0
- package/src/plugins/tailwind/plugins-tailwind/state.ts +88 -0
- package/src/plugins/tailwind/plugins-tailwind/themer.ts +53 -0
- package/src/theme/entities/variant.entity.ts +2 -1
- package/src/theme/models/variant.model.ts +7 -0
- package/src/theme/services/scheme.service.ts +31 -7
- package/src/theme/services/theme.service.ts +18 -8
- package/src/theme/services/variant.service.ts +36 -2
- package/dist/color/color-manager.service.d.ts +0 -17
- package/dist/color/color.service.d.ts +0 -16
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ConfigInterface } from './config.interface';
|
|
2
|
+
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
import { defaultColors } from '../color';
|
|
5
|
+
import { VariantModel } from '../theme';
|
|
6
|
+
import { AppService } from '../app.service';
|
|
7
|
+
|
|
8
|
+
export function defineConfig(configObject: ConfigInterface): ConfigInterface {
|
|
9
|
+
if (!configObject || typeof configObject !== 'object') {
|
|
10
|
+
throw new Error('The configuration is missing or not an object');
|
|
11
|
+
}
|
|
12
|
+
if (!('sourceColor' in configObject)) {
|
|
13
|
+
throw new Error('Invalid configuration');
|
|
14
|
+
}
|
|
15
|
+
return configObject as ConfigInterface;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ConfigService {
|
|
19
|
+
configPath = './theme.config.ts';
|
|
20
|
+
|
|
21
|
+
private appService: AppService;
|
|
22
|
+
|
|
23
|
+
constructor({ appService }: { appService: AppService }) {
|
|
24
|
+
this.appService = appService;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public async loadConfig(): Promise<void> {
|
|
28
|
+
const { themeService, colorService, pluginService } = this.appService;
|
|
29
|
+
const {
|
|
30
|
+
sourceColor,
|
|
31
|
+
contrastLevel = 0,
|
|
32
|
+
isDark = false,
|
|
33
|
+
variant = VariantModel.tonalSpot,
|
|
34
|
+
palettes,
|
|
35
|
+
colors,
|
|
36
|
+
useDefaultColors = true,
|
|
37
|
+
plugins,
|
|
38
|
+
} = await this.getConfig();
|
|
39
|
+
themeService.create({
|
|
40
|
+
contrastLevel: contrastLevel,
|
|
41
|
+
isDark: isDark,
|
|
42
|
+
sourceColorHex: sourceColor,
|
|
43
|
+
variant: variant,
|
|
44
|
+
});
|
|
45
|
+
if (palettes) {
|
|
46
|
+
Object.entries(palettes).forEach(([key, value]) =>
|
|
47
|
+
themeService.addCustomPalette(key, value)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
if (useDefaultColors) {
|
|
51
|
+
colorService.addColors(defaultColors);
|
|
52
|
+
}
|
|
53
|
+
if (colors) {
|
|
54
|
+
colorService.addColors(colors);
|
|
55
|
+
}
|
|
56
|
+
if (plugins) {
|
|
57
|
+
plugins.forEach((plugin) => {
|
|
58
|
+
if (Array.isArray(plugin)) {
|
|
59
|
+
pluginService.addPlugin(plugin[0], plugin[1]);
|
|
60
|
+
} else {
|
|
61
|
+
pluginService.addPlugin(plugin, {});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
pluginService.loadPlugins(this.appService);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private async getConfig(): Promise<ConfigInterface> {
|
|
69
|
+
const path = resolve(this.configPath);
|
|
70
|
+
const configImport = await import(path);
|
|
71
|
+
const config: unknown = configImport.default;
|
|
72
|
+
return config as ConfigInterface;
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/index.ts
CHANGED
package/src/main.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import AppContainer from './app.container';
|
|
2
2
|
import { AppService } from './app.service';
|
|
3
|
+
import { ConfigService } from './config';
|
|
3
4
|
|
|
4
|
-
export function
|
|
5
|
+
export function bootstrap(): AppService {
|
|
6
|
+
return AppContainer.resolve<AppService>('appService');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function bootstrapFromConfig(path?: string): Promise<AppService> {
|
|
10
|
+
const configService = AppContainer.resolve<ConfigService>('configService');
|
|
11
|
+
if (path) configService.configPath = path;
|
|
12
|
+
await configService.loadConfig();
|
|
5
13
|
return AppContainer.resolve<AppService>('appService');
|
|
6
14
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PluginAbstract } from './plugin.abstract';
|
|
2
|
+
import { AppService } from '../app.service';
|
|
3
|
+
|
|
4
|
+
export type PluginConstructor = new (
|
|
5
|
+
appService: AppService,
|
|
6
|
+
options: any
|
|
7
|
+
) => PluginAbstract;
|
|
8
|
+
|
|
9
|
+
export class PluginService {
|
|
10
|
+
private pluginInstances = new Map<string, PluginAbstract>();
|
|
11
|
+
private pluginConstructors = new Map<string, [PluginConstructor, object]>();
|
|
12
|
+
|
|
13
|
+
public addPlugin(plugin: PluginConstructor, config: object) {
|
|
14
|
+
this.pluginConstructors.set(plugin.name, [plugin, config]);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public loadPlugins(appService: AppService) {
|
|
18
|
+
this.pluginConstructors.forEach(([plugin, option]) => {
|
|
19
|
+
this.pluginInstances.set(plugin.name, new plugin(appService, option));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public getPlugin<T extends PluginAbstract>(
|
|
24
|
+
plugin: new (appService: AppService, options: any) => T
|
|
25
|
+
): T {
|
|
26
|
+
const pluginInstance = this.pluginInstances.get(plugin.name);
|
|
27
|
+
if (!pluginInstance) throw new Error(`Plugin ${plugin.name} not found`);
|
|
28
|
+
return pluginInstance as T;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PluginAbstract } from '../../plugin/plugin.abstract';
|
|
2
|
+
import { AppService } from '../../app.service';
|
|
3
|
+
import { Theme } from './main';
|
|
4
|
+
import { state } from './plugins-tailwind/state';
|
|
5
|
+
import { themer } from './plugins-tailwind/themer';
|
|
6
|
+
|
|
7
|
+
interface TailwindPluginOptions {
|
|
8
|
+
darkMode: 'class' | 'media';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class TailwindPlugin extends PluginAbstract {
|
|
12
|
+
constructor(
|
|
13
|
+
protected appService: AppService,
|
|
14
|
+
protected options: TailwindPluginOptions
|
|
15
|
+
) {
|
|
16
|
+
super();
|
|
17
|
+
}
|
|
18
|
+
static config(options: TailwindPluginOptions): TailwindPluginOptions {
|
|
19
|
+
return options;
|
|
20
|
+
}
|
|
21
|
+
getTheme(): Theme {
|
|
22
|
+
const colors: Record<
|
|
23
|
+
string,
|
|
24
|
+
{
|
|
25
|
+
light: string;
|
|
26
|
+
dark: string;
|
|
27
|
+
}
|
|
28
|
+
> = {};
|
|
29
|
+
|
|
30
|
+
for (const isDark of [false, true]) {
|
|
31
|
+
this.appService.themeService.update({ isDark: isDark });
|
|
32
|
+
for (const [key, value] of this.appService.colorService
|
|
33
|
+
.getColors()
|
|
34
|
+
.entries()) {
|
|
35
|
+
const newKey = key
|
|
36
|
+
.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2')
|
|
37
|
+
.toLowerCase();
|
|
38
|
+
colors[newKey] ??= { light: '', dark: '' };
|
|
39
|
+
colors[newKey][isDark ? 'dark' : 'light'] = value.getHex();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
console.log(colors);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
colors: {},
|
|
46
|
+
fontFamily: { expressive: [], neutral: [] },
|
|
47
|
+
plugins: [
|
|
48
|
+
state(Object.keys(colors)),
|
|
49
|
+
themer(colors, this.options.darkMode),
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PluginsConfig } from 'tailwindcss/types/config';
|
|
2
|
+
import { bootstrapFromConfig } from '../../main';
|
|
3
|
+
import { TailwindPlugin } from './Tailwind.plugin';
|
|
4
|
+
|
|
5
|
+
export type Theme = {
|
|
6
|
+
colors: Record<string, string>;
|
|
7
|
+
fontFamily: { expressive: string[]; neutral: string[] };
|
|
8
|
+
plugins: Partial<PluginsConfig>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const createTheme = async (): Promise<Theme> => {
|
|
12
|
+
const app = await bootstrapFromConfig();
|
|
13
|
+
const plugin = app.pluginService.getPlugin(TailwindPlugin);
|
|
14
|
+
if (!plugin) {
|
|
15
|
+
throw new Error('Tailwind plugin not found');
|
|
16
|
+
}
|
|
17
|
+
return plugin.getTheme();
|
|
18
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// from tailwindcss src/util/flattenColors
|
|
2
|
+
import plugin from 'tailwindcss/plugin';
|
|
3
|
+
import { PluginAPI } from 'tailwindcss/types/config';
|
|
4
|
+
|
|
5
|
+
type State = {
|
|
6
|
+
statePrefix: string;
|
|
7
|
+
disabledStyles: {
|
|
8
|
+
textOpacity: number;
|
|
9
|
+
backgroundOpacity: number;
|
|
10
|
+
};
|
|
11
|
+
transition: {
|
|
12
|
+
duration: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type Components = Record<string, Record<string, {}>>;
|
|
17
|
+
|
|
18
|
+
export const state = (colorkeys: string[]) =>
|
|
19
|
+
plugin((pluginArgs: PluginAPI) => {
|
|
20
|
+
addAllNewComponents(
|
|
21
|
+
pluginArgs,
|
|
22
|
+
{
|
|
23
|
+
statePrefix: 'state',
|
|
24
|
+
disabledStyles: {
|
|
25
|
+
textOpacity: 0.38,
|
|
26
|
+
backgroundOpacity: 0.12,
|
|
27
|
+
},
|
|
28
|
+
transition: {
|
|
29
|
+
duration: 150,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
colorkeys
|
|
33
|
+
);
|
|
34
|
+
}, {});
|
|
35
|
+
|
|
36
|
+
const addAllNewComponents = (
|
|
37
|
+
{ addComponents }: PluginAPI,
|
|
38
|
+
{ statePrefix, disabledStyles, transition }: State,
|
|
39
|
+
colorKeys: string[]
|
|
40
|
+
) => {
|
|
41
|
+
const newComponents: Components = {};
|
|
42
|
+
|
|
43
|
+
for (const isGroup of [false, true]) {
|
|
44
|
+
const group = isGroup ? 'group-' : '';
|
|
45
|
+
for (const colorName of colorKeys) {
|
|
46
|
+
const className = `.${group}${statePrefix}-${colorName}`;
|
|
47
|
+
newComponents[className] = {
|
|
48
|
+
[`@apply ${group}hover:bg-${colorName}/[0.08]`]: {},
|
|
49
|
+
[`@apply ${group}active:bg-${colorName}/[0.12]`]: {},
|
|
50
|
+
[`@apply ${group}focus-visible:bg-${colorName}/[0.12]`]: {},
|
|
51
|
+
};
|
|
52
|
+
if (transition) {
|
|
53
|
+
newComponents[className][`@apply transition-colors`] = {};
|
|
54
|
+
newComponents[className][`@apply duration-${transition.duration}`] = {};
|
|
55
|
+
}
|
|
56
|
+
if (disabledStyles) {
|
|
57
|
+
newComponents[className][
|
|
58
|
+
`@apply ${group}disabled:text-on-surface/[${disabledStyles.textOpacity}]`
|
|
59
|
+
] = {};
|
|
60
|
+
newComponents[className][
|
|
61
|
+
`@apply ${group}disabled:bg-on-surface/[${disabledStyles.backgroundOpacity}]`
|
|
62
|
+
] = {};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (const colorName of colorKeys) {
|
|
67
|
+
for (const stateName of ['hover', 'active', 'focus', 'disabled']) {
|
|
68
|
+
const className = `.${stateName}-${statePrefix}-${colorName}`;
|
|
69
|
+
if (stateName === 'active' || stateName === 'focus') {
|
|
70
|
+
newComponents[className] = {
|
|
71
|
+
[`@apply bg-${colorName}/[0.12]`]: {},
|
|
72
|
+
};
|
|
73
|
+
} else if (stateName === 'hover') {
|
|
74
|
+
newComponents[className] = {
|
|
75
|
+
[`@apply bg-${colorName}/[0.08]`]: {},
|
|
76
|
+
};
|
|
77
|
+
} else if (stateName === 'disabled') {
|
|
78
|
+
newComponents[className] = {
|
|
79
|
+
[`@apply text-on-surface/[${disabledStyles.textOpacity}]`]: {},
|
|
80
|
+
};
|
|
81
|
+
newComponents[className] = {
|
|
82
|
+
[`@apply bg-on-surface/[${disabledStyles.backgroundOpacity}]`]: {},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
addComponents(newComponents);
|
|
88
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export const themer = (
|
|
2
|
+
colors: Record<
|
|
3
|
+
string,
|
|
4
|
+
{
|
|
5
|
+
light: string;
|
|
6
|
+
dark: string;
|
|
7
|
+
}
|
|
8
|
+
>,
|
|
9
|
+
darkMode: 'class' | 'media'
|
|
10
|
+
) => {
|
|
11
|
+
const options: {
|
|
12
|
+
defaultTheme: {
|
|
13
|
+
extend: {
|
|
14
|
+
colors: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
themes: [
|
|
18
|
+
{
|
|
19
|
+
name: 'darkTheme';
|
|
20
|
+
selectors?: ['.dark-mode', '[data-theme="dark"]'];
|
|
21
|
+
mediaQuery?: '@media (prefers-color-scheme: dark)';
|
|
22
|
+
extend: {
|
|
23
|
+
colors: Record<string, string>;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
} = {
|
|
28
|
+
defaultTheme: {
|
|
29
|
+
extend: {
|
|
30
|
+
colors: {},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
themes: [
|
|
34
|
+
{
|
|
35
|
+
name: 'darkTheme',
|
|
36
|
+
extend: {
|
|
37
|
+
colors: {},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
Object.entries(colors).forEach(([key, value]) => {
|
|
44
|
+
options.defaultTheme.extend.colors[key] = value.light;
|
|
45
|
+
options.themes[0].extend.colors[key] = value.dark;
|
|
46
|
+
});
|
|
47
|
+
options.themes[0].selectors =
|
|
48
|
+
darkMode === 'class' ? ['.dark-mode', '[data-theme="dark"]'] : undefined;
|
|
49
|
+
options.themes[0].mediaQuery =
|
|
50
|
+
darkMode === 'media' ? '@media (prefers-color-scheme: dark)' : undefined;
|
|
51
|
+
|
|
52
|
+
return require('tailwindcss-themer')(options);
|
|
53
|
+
};
|
|
@@ -33,6 +33,7 @@ export const getRotatedHue = (
|
|
|
33
33
|
|
|
34
34
|
export class VariantEntity {
|
|
35
35
|
constructor(
|
|
36
|
-
public palettes: Record<string, (sourceColorHct: Hct) => TonalPalette> = {}
|
|
36
|
+
public palettes: Record<string, (sourceColorHct: Hct) => TonalPalette> = {},
|
|
37
|
+
public customPalettes?: (colorHct: Hct) => TonalPalette
|
|
37
38
|
) {}
|
|
38
39
|
}
|
|
@@ -21,6 +21,8 @@ export class VariantModel {
|
|
|
21
21
|
neutralVariant: (sourceColorHct) =>
|
|
22
22
|
TonalPalette.fromHueAndChroma(sourceColorHct.hue, 8.0),
|
|
23
23
|
},
|
|
24
|
+
customPalettes: (colorHct) =>
|
|
25
|
+
TonalPalette.fromHueAndChroma(colorHct.hue, 16),
|
|
24
26
|
};
|
|
25
27
|
static vibrant: VariantEntity = {
|
|
26
28
|
palettes: {
|
|
@@ -41,6 +43,11 @@ export class VariantModel {
|
|
|
41
43
|
neutralVariant: (sourceColorHct) =>
|
|
42
44
|
TonalPalette.fromHueAndChroma(sourceColorHct.hue, 8.0),
|
|
43
45
|
},
|
|
46
|
+
customPalettes: (colorHct) =>
|
|
47
|
+
TonalPalette.fromHueAndChroma(
|
|
48
|
+
getRotatedHue(colorHct, this.hues, this.secondaryRotations),
|
|
49
|
+
24.0
|
|
50
|
+
),
|
|
44
51
|
};
|
|
45
52
|
|
|
46
53
|
private static readonly hues = [
|
|
@@ -9,8 +9,14 @@ export type SchemeServiceOptions = Omit<
|
|
|
9
9
|
SchemeOptions,
|
|
10
10
|
'palettes' | 'sourceColorArgb'
|
|
11
11
|
> & {
|
|
12
|
-
|
|
13
|
-
palettes: Record<
|
|
12
|
+
sourcesColorHex: Record<string, string> & { primary?: string };
|
|
13
|
+
palettes: Record<
|
|
14
|
+
string,
|
|
15
|
+
{
|
|
16
|
+
sourceColorkey?: string;
|
|
17
|
+
tonalPalette: (sourceColorHct: Hct) => TonalPalette;
|
|
18
|
+
}
|
|
19
|
+
>;
|
|
14
20
|
};
|
|
15
21
|
|
|
16
22
|
export class SchemeService {
|
|
@@ -21,6 +27,10 @@ export class SchemeService {
|
|
|
21
27
|
this.options = {
|
|
22
28
|
...this.options,
|
|
23
29
|
...options,
|
|
30
|
+
sourcesColorHex: {
|
|
31
|
+
...this.options?.sourcesColorHex,
|
|
32
|
+
...options.sourcesColorHex,
|
|
33
|
+
},
|
|
24
34
|
palettes: {
|
|
25
35
|
...this.options?.palettes,
|
|
26
36
|
...options.palettes,
|
|
@@ -28,16 +38,30 @@ export class SchemeService {
|
|
|
28
38
|
} as SchemeServiceOptions;
|
|
29
39
|
const palettes = new Map<string, TonalPalette>();
|
|
30
40
|
|
|
31
|
-
|
|
41
|
+
if (!this.options.sourcesColorHex.primary) {
|
|
42
|
+
throw new Error('Primary source color is not set');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const sourceColorArgb = argbFromHex(this.options.sourcesColorHex.primary);
|
|
32
46
|
const sourceColorHct: Hct = Hct.fromInt(sourceColorArgb);
|
|
33
47
|
|
|
34
48
|
if (!this.options.palettes) {
|
|
35
49
|
return;
|
|
36
50
|
}
|
|
37
|
-
for (const [
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
for (const [
|
|
52
|
+
key,
|
|
53
|
+
{ sourceColorkey, tonalPalette: paletteFunction },
|
|
54
|
+
] of Object.entries(this.options.palettes)) {
|
|
55
|
+
let palette: TonalPalette;
|
|
56
|
+
if (!sourceColorkey) {
|
|
57
|
+
palette = paletteFunction(sourceColorHct);
|
|
58
|
+
} else {
|
|
59
|
+
const sourceColorArgb = argbFromHex(
|
|
60
|
+
this.options.sourcesColorHex[sourceColorkey]
|
|
61
|
+
);
|
|
62
|
+
const sourceColorHct: Hct = Hct.fromInt(sourceColorArgb);
|
|
63
|
+
palette = paletteFunction(sourceColorHct);
|
|
64
|
+
}
|
|
41
65
|
palettes.set(key, palette);
|
|
42
66
|
}
|
|
43
67
|
this.schemeEntity = new SchemeEntity({
|
|
@@ -3,7 +3,10 @@ import { SchemeService, SchemeServiceOptions } from './scheme.service';
|
|
|
3
3
|
import { VariantService } from './variant.service';
|
|
4
4
|
import { VariantEntity } from '../entities/variant.entity';
|
|
5
5
|
|
|
6
|
-
type ThemeOptions = Omit<
|
|
6
|
+
type ThemeOptions = Omit<
|
|
7
|
+
SchemeServiceOptions,
|
|
8
|
+
'palettes' | 'sourcesColorHex'
|
|
9
|
+
> & { sourceColorHex: string };
|
|
7
10
|
|
|
8
11
|
const colorPaletteKeyColor = DynamicColor.fromPalette({
|
|
9
12
|
name: 'primary_palette_key_color',
|
|
@@ -47,16 +50,23 @@ export class ThemeService {
|
|
|
47
50
|
// return this.theme();
|
|
48
51
|
// }
|
|
49
52
|
|
|
50
|
-
create(options: ThemeOptions) {
|
|
51
|
-
this.schemeService.createOrUpdate(
|
|
53
|
+
create(options: ThemeOptions & { variant: VariantEntity }) {
|
|
54
|
+
this.schemeService.createOrUpdate({
|
|
55
|
+
...options,
|
|
56
|
+
sourcesColorHex: { primary: options.sourceColorHex },
|
|
57
|
+
});
|
|
58
|
+
this.variantService.set(options.variant);
|
|
52
59
|
}
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
update(options: Partial<ThemeOptions> & { variant?: VariantEntity }) {
|
|
62
|
+
const themeOptions: Partial<SchemeServiceOptions> = { ...options };
|
|
63
|
+
if (options.sourceColorHex)
|
|
64
|
+
themeOptions.sourcesColorHex = { primary: options.sourceColorHex };
|
|
65
|
+
this.schemeService.createOrUpdate(themeOptions);
|
|
66
|
+
if (options.variant) this.variantService.set(options.variant);
|
|
56
67
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.schemeService.createOrUpdate(options);
|
|
68
|
+
addCustomPalette(key: string, colorHex: string) {
|
|
69
|
+
this.variantService.addCustomPalette(key, colorHex);
|
|
60
70
|
}
|
|
61
71
|
// theme(): SchemeService {
|
|
62
72
|
// return new SchemeService(this.themeOptions, this.colorService)
|
|
@@ -1,18 +1,52 @@
|
|
|
1
1
|
import { SchemeService } from './scheme.service';
|
|
2
2
|
import { VariantEntity } from '../entities/variant.entity';
|
|
3
|
-
import { TonalPalette } from '@material/material-color-utilities';
|
|
3
|
+
import { Hct, TonalPalette } from '@material/material-color-utilities';
|
|
4
4
|
|
|
5
5
|
export class VariantService {
|
|
6
|
+
public customPalettes: Record<string, string> = {};
|
|
7
|
+
private variantEntity?: VariantEntity;
|
|
8
|
+
|
|
6
9
|
private readonly schemeService: SchemeService;
|
|
7
10
|
constructor({ schemeService }: { schemeService: SchemeService }) {
|
|
8
11
|
this.schemeService = schemeService;
|
|
9
12
|
}
|
|
10
13
|
|
|
14
|
+
addCustomPalette(key: string, colorHex: string) {
|
|
15
|
+
this.customPalettes[key] = colorHex;
|
|
16
|
+
this.update();
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
set(variantEntity: VariantEntity) {
|
|
20
|
+
this.variantEntity = variantEntity;
|
|
12
21
|
if (!variantEntity.palettes.error) {
|
|
13
22
|
variantEntity.palettes.error = () =>
|
|
14
23
|
TonalPalette.fromHueAndChroma(25.0, 84.0);
|
|
15
24
|
}
|
|
16
|
-
this.
|
|
25
|
+
this.update();
|
|
26
|
+
}
|
|
27
|
+
private update() {
|
|
28
|
+
if (!this.variantEntity) return;
|
|
29
|
+
const palettes: Record<
|
|
30
|
+
string,
|
|
31
|
+
{
|
|
32
|
+
sourceColorkey?: string;
|
|
33
|
+
tonalPalette: (sourceColorHct: Hct) => TonalPalette;
|
|
34
|
+
}
|
|
35
|
+
> = {};
|
|
36
|
+
Object.keys(this.variantEntity.palettes).forEach((key) => {
|
|
37
|
+
palettes[key] = { tonalPalette: this.variantEntity!.palettes[key] };
|
|
38
|
+
});
|
|
39
|
+
if (this.variantEntity.customPalettes) {
|
|
40
|
+
Object.keys(this.customPalettes).forEach((key) => {
|
|
41
|
+
palettes[key] = {
|
|
42
|
+
sourceColorkey: key,
|
|
43
|
+
tonalPalette: this.variantEntity!.customPalettes!,
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
this.schemeService.createOrUpdate({
|
|
48
|
+
sourcesColorHex: this.customPalettes,
|
|
49
|
+
palettes: palettes,
|
|
50
|
+
});
|
|
17
51
|
}
|
|
18
52
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { DynamicColor } from '../material-color-utilities/dynamic_color';
|
|
2
|
-
import { SchemeEntity } from '../theme/entities/scheme.entity';
|
|
3
|
-
import { ColorEntity, ColorOptions } from './entities/color.entity';
|
|
4
|
-
import { SchemeService } from '../theme/services/scheme.service';
|
|
5
|
-
export declare const highestSurface: (s: SchemeEntity, colorManagerService: ColorManagerService) => DynamicColor;
|
|
6
|
-
export declare class ColorManagerService {
|
|
7
|
-
private colorMap;
|
|
8
|
-
private readonly schemeService;
|
|
9
|
-
constructor({ schemeService }: {
|
|
10
|
-
schemeService: SchemeService;
|
|
11
|
-
});
|
|
12
|
-
createOrUpdate(key: string, args: Partial<ColorOptions>): ColorEntity;
|
|
13
|
-
remove(key: string): boolean;
|
|
14
|
-
get(key: string): ColorEntity;
|
|
15
|
-
getAll(): ReadonlyMap<string, ColorEntity>;
|
|
16
|
-
addFromPalette(key: string): void;
|
|
17
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ColorManagerService } from './color-manager.service';
|
|
2
|
-
import { ColorInterface } from './color.interface';
|
|
3
|
-
import { ColorEntity, ColorOptions } from './entities/color.entity';
|
|
4
|
-
export declare class ColorService implements ColorInterface {
|
|
5
|
-
private readonly colorManagerService;
|
|
6
|
-
constructor({ colorManagerService, }: {
|
|
7
|
-
colorManagerService: ColorManagerService;
|
|
8
|
-
});
|
|
9
|
-
getAllColors(): ReadonlyMap<string, ColorEntity>;
|
|
10
|
-
addBaseColors(): void;
|
|
11
|
-
addColor(key: string, color: ColorOptions): ColorEntity;
|
|
12
|
-
addColors(colors: Record<string, ColorOptions>): ColorEntity[];
|
|
13
|
-
getColor(key: string): ColorEntity;
|
|
14
|
-
removeColor(key: string): boolean;
|
|
15
|
-
updateColor(key: string, newColor: Partial<ColorOptions>): ColorEntity;
|
|
16
|
-
}
|