@stackwright/themes 0.3.1 → 0.4.1
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/LICENSE +21 -0
- package/dist/index.d.mts +213 -64
- package/dist/index.d.ts +213 -64
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +25 -6
- package/AGENTS.md +0 -222
- package/CHANGELOG.md +0 -61
- package/src/ThemeProvider.tsx +0 -31
- package/src/index.ts +0 -4
- package/src/themeLoader.ts +0 -116
- package/src/themes/corporate.ts +0 -31
- package/src/themes/corporate.yaml +0 -36
- package/src/themes/soft.ts +0 -32
- package/src/themes/soft.yaml +0 -36
- package/src/types.ts +0 -66
- package/test/setup.ts +0 -1
- package/test/themeLoader.test.ts +0 -174
- package/tsconfig.json +0 -14
- package/tsup.config.ts +0 -16
- package/vitest.config.ts +0 -12
package/src/themeLoader.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import * as yaml from 'js-yaml';
|
|
2
|
-
import { Theme } from './types';
|
|
3
|
-
|
|
4
|
-
export class ThemeLoader {
|
|
5
|
-
private static themes: Map<string, Theme> = new Map();
|
|
6
|
-
|
|
7
|
-
static loadThemeFromYaml(yamlContent: string): Theme {
|
|
8
|
-
try {
|
|
9
|
-
const theme = yaml.load(yamlContent) as Theme;
|
|
10
|
-
this.themes.set(theme.name, theme);
|
|
11
|
-
return theme;
|
|
12
|
-
} catch (error) {
|
|
13
|
-
throw new Error(`Failed to parse theme YAML: ${error}`);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static loadThemeFromFile(themeName: string): Theme {
|
|
18
|
-
// In a real implementation, this would load from the file system
|
|
19
|
-
// For now, we'll embed the themes
|
|
20
|
-
const themeData = this.getEmbeddedTheme(themeName);
|
|
21
|
-
return this.loadThemeFromYaml(themeData);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static getTheme(name: string): Theme | undefined {
|
|
25
|
-
return this.themes.get(name);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static getAllThemes(): Theme[] {
|
|
29
|
-
return Array.from(this.themes.values());
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static registerCustomTheme(theme: Theme): void {
|
|
33
|
-
this.themes.set(theme.name, theme);
|
|
34
|
-
console.log(`🎨 Registered custom theme: ${theme.name}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static loadCustomTheme(theme: Theme): Theme {
|
|
38
|
-
this.registerCustomTheme(theme);
|
|
39
|
-
return theme;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
private static getEmbeddedTheme(name: string): string {
|
|
43
|
-
const themes: Record<string, string> = {
|
|
44
|
-
corporate: `
|
|
45
|
-
id: "corporate"
|
|
46
|
-
name: "Corporate"
|
|
47
|
-
description: "A professional amber-toned corporate theme"
|
|
48
|
-
colors:
|
|
49
|
-
primary: "#f59e0b"
|
|
50
|
-
secondary: "#334155"
|
|
51
|
-
accent: "#d97706"
|
|
52
|
-
background: "#f8fafc"
|
|
53
|
-
surface: "#ffffff"
|
|
54
|
-
text: "#1f2937"
|
|
55
|
-
textSecondary: "#6b7280"
|
|
56
|
-
typography:
|
|
57
|
-
fontFamily:
|
|
58
|
-
primary: "Roboto, sans-serif"
|
|
59
|
-
secondary: "Roboto, sans-serif"
|
|
60
|
-
scale:
|
|
61
|
-
xs: "0.75rem"
|
|
62
|
-
sm: "0.875rem"
|
|
63
|
-
base: "1rem"
|
|
64
|
-
lg: "1.125rem"
|
|
65
|
-
xl: "1.25rem"
|
|
66
|
-
2xl: "1.5rem"
|
|
67
|
-
3xl: "1.875rem"
|
|
68
|
-
spacing:
|
|
69
|
-
xs: "0.5rem"
|
|
70
|
-
sm: "0.75rem"
|
|
71
|
-
md: "1rem"
|
|
72
|
-
lg: "1.5rem"
|
|
73
|
-
xl: "2rem"
|
|
74
|
-
2xl: "3rem"
|
|
75
|
-
`,
|
|
76
|
-
soft: `
|
|
77
|
-
id: "soft"
|
|
78
|
-
name: "Soft"
|
|
79
|
-
description: "A gentle pink-toned soft theme"
|
|
80
|
-
colors:
|
|
81
|
-
primary: "#ec4899"
|
|
82
|
-
secondary: "#6b7280"
|
|
83
|
-
accent: "#db2777"
|
|
84
|
-
background: "#f9fafb"
|
|
85
|
-
surface: "#ffffff"
|
|
86
|
-
text: "#374151"
|
|
87
|
-
textSecondary: "#9ca3af"
|
|
88
|
-
typography:
|
|
89
|
-
fontFamily:
|
|
90
|
-
primary: "Roboto, sans-serif"
|
|
91
|
-
secondary: "Roboto, sans-serif"
|
|
92
|
-
scale:
|
|
93
|
-
xs: "0.75rem"
|
|
94
|
-
sm: "0.875rem"
|
|
95
|
-
base: "1rem"
|
|
96
|
-
lg: "1.125rem"
|
|
97
|
-
xl: "1.25rem"
|
|
98
|
-
2xl: "1.5rem"
|
|
99
|
-
3xl: "1.875rem"
|
|
100
|
-
spacing:
|
|
101
|
-
xs: "0.5rem"
|
|
102
|
-
sm: "0.75rem"
|
|
103
|
-
md: "1rem"
|
|
104
|
-
lg: "1.5rem"
|
|
105
|
-
xl: "2rem"
|
|
106
|
-
2xl: "3rem"
|
|
107
|
-
`
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
if (!themes[name]) {
|
|
111
|
-
throw new Error(`Theme '${name}' not found`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return themes[name];
|
|
115
|
-
}
|
|
116
|
-
}
|
package/src/themes/corporate.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export const corporateTheme = {
|
|
2
|
-
colors: {
|
|
3
|
-
primary: {
|
|
4
|
-
50: '#fef7ee',
|
|
5
|
-
100: '#fdedd3',
|
|
6
|
-
500: '#f59e0b', // amber-500
|
|
7
|
-
600: '#d97706', // amber-600
|
|
8
|
-
700: '#b45309', // amber-700
|
|
9
|
-
},
|
|
10
|
-
neutral: {
|
|
11
|
-
50: '#f8fafc',
|
|
12
|
-
100: '#f1f5f9',
|
|
13
|
-
700: '#334155',
|
|
14
|
-
800: '#1e293b',
|
|
15
|
-
900: '#0f172a',
|
|
16
|
-
},
|
|
17
|
-
text: {
|
|
18
|
-
primary: '#1f2937',
|
|
19
|
-
secondary: '#6b7280',
|
|
20
|
-
inverse: '#ffffff',
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
spacing: {
|
|
24
|
-
section: 'py-20',
|
|
25
|
-
container: 'max-w-7xl mx-auto px-4 sm:px-6 lg:px-8',
|
|
26
|
-
},
|
|
27
|
-
typography: {
|
|
28
|
-
hero: 'text-4xl md:text-6xl font-bold',
|
|
29
|
-
subtitle: 'text-xl md:text-2xl',
|
|
30
|
-
}
|
|
31
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
name: "Corporate"
|
|
2
|
-
colors:
|
|
3
|
-
primary:
|
|
4
|
-
50: "#fef7ee"
|
|
5
|
-
100: "#fdedd3"
|
|
6
|
-
500: "#f59e0b"
|
|
7
|
-
600: "#d97706"
|
|
8
|
-
700: "#b45309"
|
|
9
|
-
neutral:
|
|
10
|
-
50: "#f8fafc"
|
|
11
|
-
100: "#f1f5f9"
|
|
12
|
-
700: "#334155"
|
|
13
|
-
800: "#1e293b"
|
|
14
|
-
900: "#0f172a"
|
|
15
|
-
text:
|
|
16
|
-
primary: "#1f2937"
|
|
17
|
-
secondary: "#6b7280"
|
|
18
|
-
inverse: "#ffffff"
|
|
19
|
-
|
|
20
|
-
spacing:
|
|
21
|
-
section: "py-20"
|
|
22
|
-
container: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"
|
|
23
|
-
|
|
24
|
-
typography:
|
|
25
|
-
hero: "text-4xl md:text-6xl font-bold"
|
|
26
|
-
subtitle: "text-xl md:text-2xl"
|
|
27
|
-
|
|
28
|
-
components:
|
|
29
|
-
button:
|
|
30
|
-
primary: "bg-amber-600 text-white hover:bg-amber-700 px-8 py-3 rounded-lg font-semibold"
|
|
31
|
-
secondary: "text-amber-600 border border-amber-600 hover:bg-amber-50 px-8 py-3 rounded-lg font-semibold"
|
|
32
|
-
header:
|
|
33
|
-
background: "bg-white shadow-sm"
|
|
34
|
-
border: "border-b border-gray-200"
|
|
35
|
-
hero:
|
|
36
|
-
background: "bg-gradient-to-br from-slate-900 to-slate-800"
|
package/src/themes/soft.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export const softTheme = {
|
|
2
|
-
colors: {
|
|
3
|
-
primary: {
|
|
4
|
-
50: '#fdf2f8',
|
|
5
|
-
100: '#fce7f3',
|
|
6
|
-
500: '#ec4899', // pink-500
|
|
7
|
-
600: '#db2777', // pink-600
|
|
8
|
-
700: '#be185d', // pink-700
|
|
9
|
-
},
|
|
10
|
-
neutral: {
|
|
11
|
-
50: '#fefefe',
|
|
12
|
-
100: '#f9fafb',
|
|
13
|
-
700: '#6b7280',
|
|
14
|
-
800: '#4b5563',
|
|
15
|
-
900: '#374151',
|
|
16
|
-
},
|
|
17
|
-
text: {
|
|
18
|
-
primary: '#374151',
|
|
19
|
-
secondary: '#9ca3af',
|
|
20
|
-
inverse: '#ffffff',
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
spacing: {
|
|
24
|
-
section: 'py-16',
|
|
25
|
-
container: 'max-w-6xl mx-auto px-6 sm:px-8 lg:px-10',
|
|
26
|
-
},
|
|
27
|
-
typography: {
|
|
28
|
-
hero: 'text-3xl md:text-5xl font-semibold',
|
|
29
|
-
subtitle: 'text-lg md:text-xl',
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
package/src/themes/soft.yaml
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
name: "Soft"
|
|
2
|
-
colors:
|
|
3
|
-
primary:
|
|
4
|
-
50: "#fdf2f8"
|
|
5
|
-
100: "#fce7f3"
|
|
6
|
-
500: "#ec4899"
|
|
7
|
-
600: "#db2777"
|
|
8
|
-
700: "#be185d"
|
|
9
|
-
neutral:
|
|
10
|
-
50: "#fefefe"
|
|
11
|
-
100: "#f9fafb"
|
|
12
|
-
700: "#6b7280"
|
|
13
|
-
800: "#4b5563"
|
|
14
|
-
900: "#374151"
|
|
15
|
-
text:
|
|
16
|
-
primary: "#374151"
|
|
17
|
-
secondary: "#9ca3af"
|
|
18
|
-
inverse: "#ffffff"
|
|
19
|
-
|
|
20
|
-
spacing:
|
|
21
|
-
section: "py-16"
|
|
22
|
-
container: "max-w-6xl mx-auto px-6 sm:px-8 lg:px-10"
|
|
23
|
-
|
|
24
|
-
typography:
|
|
25
|
-
hero: "text-3xl md:text-5xl font-semibold"
|
|
26
|
-
subtitle: "text-lg md:text-xl"
|
|
27
|
-
|
|
28
|
-
components:
|
|
29
|
-
button:
|
|
30
|
-
primary: "bg-pink-600 text-white hover:bg-pink-700 px-6 py-2 rounded-full font-medium"
|
|
31
|
-
secondary: "text-pink-600 border border-pink-600 hover:bg-pink-50 px-6 py-2 rounded-full font-medium"
|
|
32
|
-
header:
|
|
33
|
-
background: "bg-neutral-50 shadow-none"
|
|
34
|
-
border: "border-b border-neutral-200"
|
|
35
|
-
hero:
|
|
36
|
-
background: "bg-gradient-to-br from-neutral-100 to-neutral-200"
|
package/src/types.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
export interface ThemeConfig {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
description: string;
|
|
5
|
-
colors: {
|
|
6
|
-
primary: string;
|
|
7
|
-
secondary: string;
|
|
8
|
-
accent: string;
|
|
9
|
-
background: string;
|
|
10
|
-
surface: string;
|
|
11
|
-
text: string;
|
|
12
|
-
textSecondary: string;
|
|
13
|
-
};
|
|
14
|
-
backgroundImage?: {
|
|
15
|
-
url: string;
|
|
16
|
-
repeat?: "repeat" | "repeat-x" | "repeat-y" | "no-repeat";
|
|
17
|
-
size?: "auto" | "cover" | "contain" | string;
|
|
18
|
-
position?: string;
|
|
19
|
-
attachment?: "scroll" | "fixed" | "local";
|
|
20
|
-
scale?: number;
|
|
21
|
-
animation?: "drift" | "float" | "shimmer" | "shimmer-float" | "none";
|
|
22
|
-
customAnimation?: string;
|
|
23
|
-
};
|
|
24
|
-
typography: {
|
|
25
|
-
fontFamily: {
|
|
26
|
-
primary: string;
|
|
27
|
-
secondary: string;
|
|
28
|
-
};
|
|
29
|
-
scale: {
|
|
30
|
-
xs: string;
|
|
31
|
-
sm: string;
|
|
32
|
-
base: string;
|
|
33
|
-
lg: string;
|
|
34
|
-
xl: string;
|
|
35
|
-
"2xl": string;
|
|
36
|
-
"3xl": string;
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
spacing: {
|
|
40
|
-
xs: string;
|
|
41
|
-
sm: string;
|
|
42
|
-
md: string;
|
|
43
|
-
lg: string;
|
|
44
|
-
xl: string;
|
|
45
|
-
"2xl": string;
|
|
46
|
-
};
|
|
47
|
-
components?: {
|
|
48
|
-
button?: ComponentStyle;
|
|
49
|
-
card?: ComponentStyle;
|
|
50
|
-
header?: ComponentStyle;
|
|
51
|
-
footer?: ComponentStyle;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface ComponentStyle {
|
|
56
|
-
base?: string;
|
|
57
|
-
primary?: string;
|
|
58
|
-
secondary?: string;
|
|
59
|
-
outline?: string;
|
|
60
|
-
shadow?: string;
|
|
61
|
-
nav?: string;
|
|
62
|
-
text?: string;
|
|
63
|
-
[key: string]: string | undefined;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface Theme extends ThemeConfig {}
|
package/test/setup.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// Vitest setup for @stackwright/themes
|
package/test/themeLoader.test.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
-
import { ThemeLoader } from '../src/themeLoader';
|
|
3
|
-
import type { Theme } from '../src/types';
|
|
4
|
-
|
|
5
|
-
// The ThemeLoader uses a static Map, so we need to be careful about state
|
|
6
|
-
// leaking between tests. We work around this by using unique theme names.
|
|
7
|
-
|
|
8
|
-
const makeCustomTheme = (overrides: Partial<Theme> = {}): Theme => ({
|
|
9
|
-
id: 'test-theme',
|
|
10
|
-
name: 'Test Theme',
|
|
11
|
-
description: 'A theme for testing',
|
|
12
|
-
colors: {
|
|
13
|
-
primary: '#aabbcc',
|
|
14
|
-
secondary: '#112233',
|
|
15
|
-
accent: '#ccbbaa',
|
|
16
|
-
background: '#ffffff',
|
|
17
|
-
surface: '#f0f0f0',
|
|
18
|
-
text: '#000000',
|
|
19
|
-
textSecondary: '#666666',
|
|
20
|
-
},
|
|
21
|
-
typography: {
|
|
22
|
-
fontFamily: { primary: 'Arial, sans-serif', secondary: 'Georgia, serif' },
|
|
23
|
-
scale: {
|
|
24
|
-
xs: '0.75rem', sm: '0.875rem', base: '1rem',
|
|
25
|
-
lg: '1.125rem', xl: '1.25rem', '2xl': '1.5rem', '3xl': '1.875rem',
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
spacing: {
|
|
29
|
-
xs: '0.5rem', sm: '0.75rem', md: '1rem',
|
|
30
|
-
lg: '1.5rem', xl: '2rem', '2xl': '3rem',
|
|
31
|
-
},
|
|
32
|
-
...overrides,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
describe('ThemeLoader.loadThemeFromFile', () => {
|
|
36
|
-
it('loads the corporate theme and returns a valid ThemeConfig', () => {
|
|
37
|
-
const theme = ThemeLoader.loadThemeFromFile('corporate');
|
|
38
|
-
expect(theme).toBeDefined();
|
|
39
|
-
expect(theme.name).toBe('Corporate');
|
|
40
|
-
expect(theme.id).toBe('corporate');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('corporate theme has flat hex string colors (not nested objects)', () => {
|
|
44
|
-
const theme = ThemeLoader.loadThemeFromFile('corporate');
|
|
45
|
-
expect(typeof theme.colors.primary).toBe('string');
|
|
46
|
-
expect(theme.colors.primary).toMatch(/^#[0-9a-fA-F]{6}$/);
|
|
47
|
-
expect(typeof theme.colors.secondary).toBe('string');
|
|
48
|
-
expect(typeof theme.colors.background).toBe('string');
|
|
49
|
-
expect(typeof theme.colors.surface).toBe('string');
|
|
50
|
-
expect(typeof theme.colors.text).toBe('string');
|
|
51
|
-
expect(typeof theme.colors.textSecondary).toBe('string');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('loads the soft theme and returns a valid ThemeConfig', () => {
|
|
55
|
-
const theme = ThemeLoader.loadThemeFromFile('soft');
|
|
56
|
-
expect(theme).toBeDefined();
|
|
57
|
-
expect(theme.name).toBe('Soft');
|
|
58
|
-
expect(theme.id).toBe('soft');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('soft theme has flat hex string colors', () => {
|
|
62
|
-
const theme = ThemeLoader.loadThemeFromFile('soft');
|
|
63
|
-
expect(typeof theme.colors.primary).toBe('string');
|
|
64
|
-
expect(theme.colors.primary).toMatch(/^#[0-9a-fA-F]{6}$/);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('throws for an unknown theme name', () => {
|
|
68
|
-
expect(() => ThemeLoader.loadThemeFromFile('nonexistent')).toThrow(
|
|
69
|
-
"Theme 'nonexistent' not found"
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('loaded themes have required typography and spacing fields', () => {
|
|
74
|
-
const theme = ThemeLoader.loadThemeFromFile('corporate');
|
|
75
|
-
expect(theme.typography).toBeDefined();
|
|
76
|
-
expect(theme.typography.fontFamily.primary).toBeTruthy();
|
|
77
|
-
expect(theme.spacing).toBeDefined();
|
|
78
|
-
expect(theme.spacing.md).toBeTruthy();
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
describe('ThemeLoader.loadThemeFromYaml', () => {
|
|
83
|
-
it('parses valid YAML and returns a theme', () => {
|
|
84
|
-
const yaml = `
|
|
85
|
-
id: "yaml-test"
|
|
86
|
-
name: "YAML Test"
|
|
87
|
-
description: "Parsed from YAML"
|
|
88
|
-
colors:
|
|
89
|
-
primary: "#ff0000"
|
|
90
|
-
secondary: "#00ff00"
|
|
91
|
-
accent: "#0000ff"
|
|
92
|
-
background: "#ffffff"
|
|
93
|
-
surface: "#eeeeee"
|
|
94
|
-
text: "#111111"
|
|
95
|
-
textSecondary: "#555555"
|
|
96
|
-
typography:
|
|
97
|
-
fontFamily:
|
|
98
|
-
primary: "Roboto, sans-serif"
|
|
99
|
-
secondary: "Roboto, sans-serif"
|
|
100
|
-
scale:
|
|
101
|
-
xs: "0.75rem"
|
|
102
|
-
sm: "0.875rem"
|
|
103
|
-
base: "1rem"
|
|
104
|
-
lg: "1.125rem"
|
|
105
|
-
xl: "1.25rem"
|
|
106
|
-
2xl: "1.5rem"
|
|
107
|
-
3xl: "1.875rem"
|
|
108
|
-
spacing:
|
|
109
|
-
xs: "0.5rem"
|
|
110
|
-
sm: "0.75rem"
|
|
111
|
-
md: "1rem"
|
|
112
|
-
lg: "1.5rem"
|
|
113
|
-
xl: "2rem"
|
|
114
|
-
2xl: "3rem"
|
|
115
|
-
`;
|
|
116
|
-
const theme = ThemeLoader.loadThemeFromYaml(yaml);
|
|
117
|
-
expect(theme.name).toBe('YAML Test');
|
|
118
|
-
expect(theme.colors.primary).toBe('#ff0000');
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('throws for invalid YAML syntax', () => {
|
|
122
|
-
expect(() =>
|
|
123
|
-
ThemeLoader.loadThemeFromYaml('{ invalid: yaml: content: :')
|
|
124
|
-
).toThrow('Failed to parse theme YAML');
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('ThemeLoader.registerCustomTheme / getTheme', () => {
|
|
129
|
-
it('registers a custom theme and retrieves it by name', () => {
|
|
130
|
-
const custom = makeCustomTheme({ name: 'My Custom Theme A' });
|
|
131
|
-
ThemeLoader.registerCustomTheme(custom);
|
|
132
|
-
const retrieved = ThemeLoader.getTheme('My Custom Theme A');
|
|
133
|
-
expect(retrieved).toBeDefined();
|
|
134
|
-
expect(retrieved?.colors.primary).toBe('#aabbcc');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('getTheme returns undefined for an unregistered name', () => {
|
|
138
|
-
expect(ThemeLoader.getTheme('__does_not_exist__')).toBeUndefined();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('overwriting a theme by name replaces it', () => {
|
|
142
|
-
const v1 = makeCustomTheme({ name: 'Overwrite Test', colors: { ...makeCustomTheme().colors, primary: '#111111' } });
|
|
143
|
-
const v2 = makeCustomTheme({ name: 'Overwrite Test', colors: { ...makeCustomTheme().colors, primary: '#222222' } });
|
|
144
|
-
ThemeLoader.registerCustomTheme(v1);
|
|
145
|
-
ThemeLoader.registerCustomTheme(v2);
|
|
146
|
-
expect(ThemeLoader.getTheme('Overwrite Test')?.colors.primary).toBe('#222222');
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
describe('ThemeLoader.loadCustomTheme', () => {
|
|
151
|
-
it('registers the theme and returns it', () => {
|
|
152
|
-
const custom = makeCustomTheme({ name: 'LoadCustom Test' });
|
|
153
|
-
const returned = ThemeLoader.loadCustomTheme(custom);
|
|
154
|
-
expect(returned).toBe(custom);
|
|
155
|
-
expect(ThemeLoader.getTheme('LoadCustom Test')).toBeDefined();
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
describe('ThemeLoader.getAllThemes', () => {
|
|
160
|
-
it('returns an array (may include themes registered by other tests)', () => {
|
|
161
|
-
// Load a known theme to ensure at least one is present
|
|
162
|
-
ThemeLoader.loadThemeFromFile('corporate');
|
|
163
|
-
const all = ThemeLoader.getAllThemes();
|
|
164
|
-
expect(Array.isArray(all)).toBe(true);
|
|
165
|
-
expect(all.length).toBeGreaterThan(0);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('includes a custom theme after registration', () => {
|
|
169
|
-
const uniqueName = `AllThemes-${Date.now()}`;
|
|
170
|
-
ThemeLoader.registerCustomTheme(makeCustomTheme({ name: uniqueName }));
|
|
171
|
-
const names = ThemeLoader.getAllThemes().map(t => t.name);
|
|
172
|
-
expect(names).toContain(uniqueName);
|
|
173
|
-
});
|
|
174
|
-
});
|
package/tsconfig.json
DELETED
package/tsup.config.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'tsup';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
entry: ['src/index.ts'],
|
|
5
|
-
format: ['cjs', 'esm'],
|
|
6
|
-
dts: true,
|
|
7
|
-
target: 'es2022',
|
|
8
|
-
splitting: false,
|
|
9
|
-
sourcemap: true,
|
|
10
|
-
clean: true,
|
|
11
|
-
outExtension({ format }) {
|
|
12
|
-
return {
|
|
13
|
-
js: format === 'cjs' ? '.js' : '.mjs',
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
});
|