@autumnsgrove/gossamer 0.1.1 → 0.2.0
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/animation.js +165 -0
- package/dist/animation.test.js +204 -0
- package/dist/characters.js +176 -0
- package/dist/characters.test.js +115 -0
- package/dist/colors.js +199 -0
- package/dist/index.js +79 -1850
- package/dist/index.test.js +92 -0
- package/dist/patterns.js +539 -0
- package/dist/patterns.test.js +223 -0
- package/dist/renderer.js +362 -0
- package/dist/svelte/GossamerBorder.svelte.d.ts +56 -1
- package/dist/svelte/GossamerBorder.svelte.d.ts.map +1 -0
- package/dist/svelte/GossamerClouds.svelte.d.ts +31 -1
- package/dist/svelte/GossamerClouds.svelte.d.ts.map +1 -0
- package/dist/svelte/GossamerImage.svelte.d.ts +28 -1
- package/dist/svelte/GossamerImage.svelte.d.ts.map +1 -0
- package/dist/svelte/GossamerOverlay.svelte.d.ts +32 -1
- package/dist/svelte/GossamerOverlay.svelte.d.ts.map +1 -0
- package/dist/svelte/GossamerText.svelte.d.ts +29 -1
- package/dist/svelte/GossamerText.svelte.d.ts.map +1 -0
- package/dist/svelte/index.js +31 -3646
- package/dist/svelte/presets.d.ts +4 -2
- package/dist/svelte/presets.js +161 -0
- package/dist/utils/canvas.js +139 -0
- package/dist/utils/image.js +195 -0
- package/dist/utils/performance.js +205 -0
- package/package.json +18 -22
- package/dist/index.js.map +0 -1
- package/dist/style.css +0 -124
- package/dist/svelte/index.js.map +0 -1
- package/src/animation.test.ts +0 -254
- package/src/animation.ts +0 -243
- package/src/characters.test.ts +0 -148
- package/src/characters.ts +0 -219
- package/src/colors.ts +0 -234
- package/src/index.test.ts +0 -115
- package/src/index.ts +0 -234
- package/src/patterns.test.ts +0 -273
- package/src/patterns.ts +0 -760
- package/src/renderer.ts +0 -470
- package/src/svelte/index.ts +0 -75
- package/src/svelte/presets.ts +0 -174
- package/src/utils/canvas.ts +0 -210
- package/src/utils/image.ts +0 -275
- package/src/utils/performance.ts +0 -282
- /package/{src → dist}/svelte/GossamerBorder.svelte +0 -0
- /package/{src → dist}/svelte/GossamerClouds.svelte +0 -0
- /package/{src → dist}/svelte/GossamerImage.svelte +0 -0
- /package/{src → dist}/svelte/GossamerOverlay.svelte +0 -0
- /package/{src → dist}/svelte/GossamerText.svelte +0 -0
package/src/characters.ts
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gossamer Character Sets
|
|
3
|
-
*
|
|
4
|
-
* Predefined character sets for ASCII rendering, ordered from light to dark.
|
|
5
|
-
* Character density determines which character represents each brightness level.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Character set configuration
|
|
10
|
-
*/
|
|
11
|
-
export interface CharacterSet {
|
|
12
|
-
/** Unique identifier for the character set */
|
|
13
|
-
name: string;
|
|
14
|
-
/** Description of the set's aesthetic */
|
|
15
|
-
description: string;
|
|
16
|
-
/** Characters ordered from lightest (space) to darkest */
|
|
17
|
-
characters: string;
|
|
18
|
-
/** Recommended use cases */
|
|
19
|
-
bestFor: string[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Standard character sets for ASCII rendering
|
|
24
|
-
*/
|
|
25
|
-
export const CHARACTER_SETS: Record<string, CharacterSet> = {
|
|
26
|
-
standard: {
|
|
27
|
-
name: 'Standard',
|
|
28
|
-
description: 'Classic ASCII art character set',
|
|
29
|
-
characters: ' .:-=+*#%@',
|
|
30
|
-
bestFor: ['general', 'images', 'patterns'],
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
dense: {
|
|
34
|
-
name: 'Dense',
|
|
35
|
-
description: 'High detail character set with many gradations',
|
|
36
|
-
characters: " .'`^\",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$",
|
|
37
|
-
bestFor: ['detailed images', 'portraits', 'high contrast'],
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
minimal: {
|
|
41
|
-
name: 'Minimal',
|
|
42
|
-
description: 'Clean and simple with few characters',
|
|
43
|
-
characters: ' .:*#',
|
|
44
|
-
bestFor: ['backgrounds', 'subtle effects', 'clean aesthetic'],
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
grove: {
|
|
48
|
-
name: 'Grove',
|
|
49
|
-
description: 'Organic, soft characters inspired by nature',
|
|
50
|
-
characters: ' ·∙•◦○◉●',
|
|
51
|
-
bestFor: ['organic patterns', 'soft backgrounds', 'nature themes'],
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
dots: {
|
|
55
|
-
name: 'Dots',
|
|
56
|
-
description: 'Braille-like dot patterns',
|
|
57
|
-
characters: ' ⋅∘∙●',
|
|
58
|
-
bestFor: ['stipple effects', 'pointillism', 'dotted textures'],
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
blocks: {
|
|
62
|
-
name: 'Blocks',
|
|
63
|
-
description: 'Block-based characters for sharp edges',
|
|
64
|
-
characters: ' ░▒▓█',
|
|
65
|
-
bestFor: ['retro effects', 'pixel art', 'bold patterns'],
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
lines: {
|
|
69
|
-
name: 'Lines',
|
|
70
|
-
description: 'Line-based characters for directional effects',
|
|
71
|
-
characters: ' -─═╌│┃',
|
|
72
|
-
bestFor: ['rain effects', 'streaks', 'motion blur'],
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
stars: {
|
|
76
|
-
name: 'Stars',
|
|
77
|
-
description: 'Star and sparkle characters',
|
|
78
|
-
characters: ' ·✧✦✫✬✯★',
|
|
79
|
-
bestFor: ['sparkle effects', 'night sky', 'magical themes'],
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
nature: {
|
|
83
|
-
name: 'Nature',
|
|
84
|
-
description: 'Nature-themed decorative characters',
|
|
85
|
-
characters: ' .~≈∿⌇☘',
|
|
86
|
-
bestFor: ['decorative', 'themed effects', 'organic patterns'],
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
weather: {
|
|
90
|
-
name: 'Weather',
|
|
91
|
-
description: 'Weather-related symbols',
|
|
92
|
-
characters: ' ·.:*❄❅❆',
|
|
93
|
-
bestFor: ['snow effects', 'weather simulations', 'seasonal themes'],
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
binary: {
|
|
97
|
-
name: 'Binary',
|
|
98
|
-
description: 'Digital-style binary characters',
|
|
99
|
-
characters: ' 01',
|
|
100
|
-
bestFor: ['digital effects', 'matrix style', 'tech themes'],
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
math: {
|
|
104
|
-
name: 'Math',
|
|
105
|
-
description: 'Mathematical symbols',
|
|
106
|
-
characters: ' +-×÷=≠≈∞',
|
|
107
|
-
bestFor: ['abstract patterns', 'tech themes', 'decorative'],
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
// ==========================================================================
|
|
111
|
-
// GLASS-OPTIMIZED CHARACTER SETS
|
|
112
|
-
// Designed for subtle overlays on Glass components
|
|
113
|
-
// More characters = more visible gradations
|
|
114
|
-
// ==========================================================================
|
|
115
|
-
|
|
116
|
-
'glass-dots': {
|
|
117
|
-
name: 'Glass Dots',
|
|
118
|
-
description: 'Soft dot gradations for glass overlays',
|
|
119
|
-
characters: ' ·∘∙○•●',
|
|
120
|
-
bestFor: ['glass overlays', 'subtle backgrounds', 'mist effects'],
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
'glass-mist': {
|
|
124
|
-
name: 'Glass Mist',
|
|
125
|
-
description: 'Ethereal mist effect for glass',
|
|
126
|
-
characters: ' .·∙•◦○◉●',
|
|
127
|
-
bestFor: ['glass overlays', 'fog effects', 'ambient backgrounds'],
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
'glass-dust': {
|
|
131
|
-
name: 'Glass Dust',
|
|
132
|
-
description: 'Floating dust particles',
|
|
133
|
-
characters: ' ˙·∘°•◦○',
|
|
134
|
-
bestFor: ['glass overlays', 'particle effects', 'light scatter'],
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
'glass-soft': {
|
|
138
|
-
name: 'Glass Soft',
|
|
139
|
-
description: 'Soft block gradations for glass',
|
|
140
|
-
characters: ' ·░▒▓',
|
|
141
|
-
bestFor: ['glass overlays', 'soft gradients', 'frosted effect'],
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
'glass-sparkle': {
|
|
145
|
-
name: 'Glass Sparkle',
|
|
146
|
-
description: 'Subtle sparkles for glass',
|
|
147
|
-
characters: ' ·.✧✦✫★',
|
|
148
|
-
bestFor: ['glass overlays', 'highlight effects', 'magical themes'],
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
'glass-wave': {
|
|
152
|
-
name: 'Glass Wave',
|
|
153
|
-
description: 'Flowing wave patterns for glass',
|
|
154
|
-
characters: ' .~∼≈≋',
|
|
155
|
-
bestFor: ['glass overlays', 'water effects', 'flowing motion'],
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
'glass-organic': {
|
|
159
|
-
name: 'Glass Organic',
|
|
160
|
-
description: 'Natural, organic feel for glass',
|
|
161
|
-
characters: ' .·:;∘○◦•●',
|
|
162
|
-
bestFor: ['glass overlays', 'nature themes', 'grove aesthetic'],
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Get a character set by name
|
|
168
|
-
*/
|
|
169
|
-
export function getCharacterSet(name: string): CharacterSet | undefined {
|
|
170
|
-
return CHARACTER_SETS[name];
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Get just the characters string from a named set
|
|
175
|
-
*/
|
|
176
|
-
export function getCharacters(name: string): string {
|
|
177
|
-
return CHARACTER_SETS[name]?.characters || CHARACTER_SETS.standard.characters;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* List all available character set names
|
|
182
|
-
*/
|
|
183
|
-
export function getCharacterSetNames(): string[] {
|
|
184
|
-
return Object.keys(CHARACTER_SETS);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Create a custom character set
|
|
189
|
-
*/
|
|
190
|
-
export function createCharacterSet(
|
|
191
|
-
name: string,
|
|
192
|
-
characters: string,
|
|
193
|
-
description: string = '',
|
|
194
|
-
bestFor: string[] = []
|
|
195
|
-
): CharacterSet {
|
|
196
|
-
return {
|
|
197
|
-
name,
|
|
198
|
-
description,
|
|
199
|
-
characters,
|
|
200
|
-
bestFor,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Validate that a character string is suitable for ASCII rendering
|
|
206
|
-
* (should start with space and have at least 2 characters)
|
|
207
|
-
*/
|
|
208
|
-
export function validateCharacterSet(characters: string): boolean {
|
|
209
|
-
if (characters.length < 2) return false;
|
|
210
|
-
if (characters[0] !== ' ') return false;
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Reverse a character set (for inverted brightness mapping)
|
|
216
|
-
*/
|
|
217
|
-
export function invertCharacters(characters: string): string {
|
|
218
|
-
return characters.split('').reverse().join('');
|
|
219
|
-
}
|
package/src/colors.ts
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gossamer Color Palettes
|
|
3
|
-
*
|
|
4
|
-
* Grove-themed color palettes for ASCII effects.
|
|
5
|
-
* Designed to complement Glass UI components.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Color definition with metadata
|
|
10
|
-
*/
|
|
11
|
-
export interface ColorDef {
|
|
12
|
-
/** Hex color value */
|
|
13
|
-
hex: string;
|
|
14
|
-
/** Human-readable name */
|
|
15
|
-
name: string;
|
|
16
|
-
/** Recommended opacity for glass overlays (0-1) */
|
|
17
|
-
glassOpacity?: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Grove Green palette - Primary brand colors
|
|
22
|
-
*/
|
|
23
|
-
export const GROVE_GREEN = {
|
|
24
|
-
50: { hex: '#f0fdf4', name: 'Grove Green 50', glassOpacity: 0.3 },
|
|
25
|
-
100: { hex: '#dcfce7', name: 'Grove Green 100', glassOpacity: 0.25 },
|
|
26
|
-
200: { hex: '#bbf7d0', name: 'Grove Green 200', glassOpacity: 0.2 },
|
|
27
|
-
300: { hex: '#86efac', name: 'Grove Green 300', glassOpacity: 0.18 },
|
|
28
|
-
400: { hex: '#4ade80', name: 'Grove Green 400', glassOpacity: 0.15 },
|
|
29
|
-
500: { hex: '#22c55e', name: 'Grove Green 500', glassOpacity: 0.12 },
|
|
30
|
-
600: { hex: '#16a34a', name: 'Grove Green 600', glassOpacity: 0.1 },
|
|
31
|
-
700: { hex: '#15803d', name: 'Grove Green 700', glassOpacity: 0.1 },
|
|
32
|
-
800: { hex: '#166534', name: 'Grove Green 800', glassOpacity: 0.08 },
|
|
33
|
-
900: { hex: '#14532d', name: 'Grove Green 900', glassOpacity: 0.08 },
|
|
34
|
-
} as const;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Cream palette - Light/warm backgrounds
|
|
38
|
-
*/
|
|
39
|
-
export const CREAM = {
|
|
40
|
-
50: { hex: '#fefdfb', name: 'Cream 50', glassOpacity: 0.4 },
|
|
41
|
-
100: { hex: '#fdfcf8', name: 'Cream 100', glassOpacity: 0.35 },
|
|
42
|
-
200: { hex: '#faf8f3', name: 'Cream 200', glassOpacity: 0.3 },
|
|
43
|
-
300: { hex: '#f5f2ea', name: 'Cream 300', glassOpacity: 0.25 },
|
|
44
|
-
400: { hex: '#ede9de', name: 'Cream 400', glassOpacity: 0.2 },
|
|
45
|
-
500: { hex: '#e2ddd0', name: 'Cream 500', glassOpacity: 0.18 },
|
|
46
|
-
600: { hex: '#d4cec0', name: 'Cream 600', glassOpacity: 0.15 },
|
|
47
|
-
700: { hex: '#c4bdb0', name: 'Cream 700', glassOpacity: 0.12 },
|
|
48
|
-
800: { hex: '#b0a99c', name: 'Cream 800', glassOpacity: 0.1 },
|
|
49
|
-
900: { hex: '#9a9387', name: 'Cream 900', glassOpacity: 0.08 },
|
|
50
|
-
} as const;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Bark palette - Dark/earth tones
|
|
54
|
-
*/
|
|
55
|
-
export const BARK = {
|
|
56
|
-
50: { hex: '#faf7f5', name: 'Bark 50', glassOpacity: 0.3 },
|
|
57
|
-
100: { hex: '#f0ebe6', name: 'Bark 100', glassOpacity: 0.25 },
|
|
58
|
-
200: { hex: '#e0d5cc', name: 'Bark 200', glassOpacity: 0.2 },
|
|
59
|
-
300: { hex: '#ccb59c', name: 'Bark 300', glassOpacity: 0.18 },
|
|
60
|
-
400: { hex: '#b89a7a', name: 'Bark 400', glassOpacity: 0.15 },
|
|
61
|
-
500: { hex: '#a57c5a', name: 'Bark 500', glassOpacity: 0.12 },
|
|
62
|
-
600: { hex: '#8a6344', name: 'Bark 600', glassOpacity: 0.1 },
|
|
63
|
-
700: { hex: '#6f4d39', name: 'Bark 700', glassOpacity: 0.1 },
|
|
64
|
-
800: { hex: '#553a2a', name: 'Bark 800', glassOpacity: 0.08 },
|
|
65
|
-
900: { hex: '#3d2914', name: 'Bark 900', glassOpacity: 0.06 },
|
|
66
|
-
} as const;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Status colors
|
|
70
|
-
*/
|
|
71
|
-
export const STATUS = {
|
|
72
|
-
success: { hex: '#22c55e', name: 'Success', glassOpacity: 0.12 },
|
|
73
|
-
warning: { hex: '#f59e0b', name: 'Warning', glassOpacity: 0.12 },
|
|
74
|
-
error: { hex: '#dc2626', name: 'Error', glassOpacity: 0.1 },
|
|
75
|
-
info: { hex: '#0ea5e9', name: 'Info', glassOpacity: 0.12 },
|
|
76
|
-
} as const;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Combined Grove color schemes for easy access
|
|
80
|
-
*/
|
|
81
|
-
export const GROVE_COLORS = {
|
|
82
|
-
// Greens
|
|
83
|
-
grove: GROVE_GREEN[500].hex,
|
|
84
|
-
'grove-light': GROVE_GREEN[300].hex,
|
|
85
|
-
'grove-dark': GROVE_GREEN[700].hex,
|
|
86
|
-
'grove-muted': GROVE_GREEN[400].hex,
|
|
87
|
-
|
|
88
|
-
// Creams
|
|
89
|
-
cream: CREAM[50].hex,
|
|
90
|
-
'cream-warm': CREAM[200].hex,
|
|
91
|
-
'cream-deep': CREAM[500].hex,
|
|
92
|
-
|
|
93
|
-
// Barks
|
|
94
|
-
bark: BARK[900].hex,
|
|
95
|
-
'bark-light': BARK[500].hex,
|
|
96
|
-
'bark-medium': BARK[700].hex,
|
|
97
|
-
|
|
98
|
-
// Utility
|
|
99
|
-
white: '#ffffff',
|
|
100
|
-
black: '#000000',
|
|
101
|
-
transparent: 'transparent',
|
|
102
|
-
} as const;
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Glass-optimized color schemes
|
|
106
|
-
* Pre-configured for use with Glass components
|
|
107
|
-
*/
|
|
108
|
-
export const GLASS_SCHEMES = {
|
|
109
|
-
// Light mode schemes (on light backgrounds)
|
|
110
|
-
'grove-mist': {
|
|
111
|
-
color: GROVE_GREEN[500].hex,
|
|
112
|
-
background: 'transparent',
|
|
113
|
-
opacity: 0.12,
|
|
114
|
-
description: 'Subtle green mist for light glass',
|
|
115
|
-
},
|
|
116
|
-
'cream-haze': {
|
|
117
|
-
color: CREAM[600].hex,
|
|
118
|
-
background: 'transparent',
|
|
119
|
-
opacity: 0.15,
|
|
120
|
-
description: 'Warm cream haze for cozy glass',
|
|
121
|
-
},
|
|
122
|
-
'bark-shadow': {
|
|
123
|
-
color: BARK[700].hex,
|
|
124
|
-
background: 'transparent',
|
|
125
|
-
opacity: 0.08,
|
|
126
|
-
description: 'Soft earth shadow for depth',
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
// Dark mode schemes (on dark backgrounds)
|
|
130
|
-
'grove-glow': {
|
|
131
|
-
color: GROVE_GREEN[400].hex,
|
|
132
|
-
background: '#1a1915',
|
|
133
|
-
opacity: 0.15,
|
|
134
|
-
description: 'Glowing green for dark glass',
|
|
135
|
-
},
|
|
136
|
-
'cream-dust': {
|
|
137
|
-
color: CREAM[300].hex,
|
|
138
|
-
background: '#1a1915',
|
|
139
|
-
opacity: 0.1,
|
|
140
|
-
description: 'Dusty cream particles in dark',
|
|
141
|
-
},
|
|
142
|
-
'moonlight': {
|
|
143
|
-
color: '#e2e8f0',
|
|
144
|
-
background: '#1a1915',
|
|
145
|
-
opacity: 0.08,
|
|
146
|
-
description: 'Cool moonlight glow',
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
// Accent schemes
|
|
150
|
-
'spring-fresh': {
|
|
151
|
-
color: GROVE_GREEN[300].hex,
|
|
152
|
-
background: 'transparent',
|
|
153
|
-
opacity: 0.18,
|
|
154
|
-
description: 'Fresh spring green overlay',
|
|
155
|
-
},
|
|
156
|
-
'autumn-warm': {
|
|
157
|
-
color: '#d97706',
|
|
158
|
-
background: 'transparent',
|
|
159
|
-
opacity: 0.1,
|
|
160
|
-
description: 'Warm autumn amber tones',
|
|
161
|
-
},
|
|
162
|
-
'winter-frost': {
|
|
163
|
-
color: '#93c5fd',
|
|
164
|
-
background: 'transparent',
|
|
165
|
-
opacity: 0.12,
|
|
166
|
-
description: 'Cool frost blue overlay',
|
|
167
|
-
},
|
|
168
|
-
} as const;
|
|
169
|
-
|
|
170
|
-
export type GroveColorName = keyof typeof GROVE_COLORS;
|
|
171
|
-
export type GlassSchemeName = keyof typeof GLASS_SCHEMES;
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Get a Grove color by name
|
|
175
|
-
*/
|
|
176
|
-
export function getGroveColor(name: GroveColorName | string): string {
|
|
177
|
-
if (name in GROVE_COLORS) {
|
|
178
|
-
return GROVE_COLORS[name as GroveColorName];
|
|
179
|
-
}
|
|
180
|
-
// If it's already a hex color, return it
|
|
181
|
-
if (name.startsWith('#')) {
|
|
182
|
-
return name;
|
|
183
|
-
}
|
|
184
|
-
// Default to grove green
|
|
185
|
-
return GROVE_COLORS.grove;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Get a glass scheme by name
|
|
190
|
-
*/
|
|
191
|
-
export function getGlassScheme(name: GlassSchemeName | string): {
|
|
192
|
-
color: string;
|
|
193
|
-
background: string;
|
|
194
|
-
opacity: number;
|
|
195
|
-
} {
|
|
196
|
-
if (name in GLASS_SCHEMES) {
|
|
197
|
-
const scheme = GLASS_SCHEMES[name as GlassSchemeName];
|
|
198
|
-
return {
|
|
199
|
-
color: scheme.color,
|
|
200
|
-
background: scheme.background,
|
|
201
|
-
opacity: scheme.opacity,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
// Default to grove-mist
|
|
205
|
-
return {
|
|
206
|
-
color: GLASS_SCHEMES['grove-mist'].color,
|
|
207
|
-
background: GLASS_SCHEMES['grove-mist'].background,
|
|
208
|
-
opacity: GLASS_SCHEMES['grove-mist'].opacity,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* List all Grove color names
|
|
214
|
-
*/
|
|
215
|
-
export function getGroveColorNames(): string[] {
|
|
216
|
-
return Object.keys(GROVE_COLORS);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* List all glass scheme names
|
|
221
|
-
*/
|
|
222
|
-
export function getGlassSchemeNames(): string[] {
|
|
223
|
-
return Object.keys(GLASS_SCHEMES);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Apply opacity to a hex color, returning rgba string
|
|
228
|
-
*/
|
|
229
|
-
export function hexToRgba(hex: string, opacity: number): string {
|
|
230
|
-
const r = parseInt(hex.slice(1, 3), 16);
|
|
231
|
-
const g = parseInt(hex.slice(3, 5), 16);
|
|
232
|
-
const b = parseInt(hex.slice(5, 7), 16);
|
|
233
|
-
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
234
|
-
}
|
package/src/index.test.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for core index functions
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect } from 'vitest';
|
|
5
|
-
import {
|
|
6
|
-
calculateBrightness,
|
|
7
|
-
brightnessToChar,
|
|
8
|
-
DEFAULT_CHARACTERS,
|
|
9
|
-
DEFAULT_CONFIG,
|
|
10
|
-
VERSION,
|
|
11
|
-
} from './index';
|
|
12
|
-
|
|
13
|
-
describe('calculateBrightness', () => {
|
|
14
|
-
it('should return 0 for black', () => {
|
|
15
|
-
expect(calculateBrightness(0, 0, 0)).toBe(0);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should return 255 for white', () => {
|
|
19
|
-
expect(calculateBrightness(255, 255, 255)).toBeCloseTo(255, 5);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should weight green highest', () => {
|
|
23
|
-
// Green contributes 0.72, so pure green should be brighter than pure red
|
|
24
|
-
const greenBrightness = calculateBrightness(0, 255, 0);
|
|
25
|
-
const redBrightness = calculateBrightness(255, 0, 0);
|
|
26
|
-
const blueBrightness = calculateBrightness(0, 0, 255);
|
|
27
|
-
|
|
28
|
-
expect(greenBrightness).toBeGreaterThan(redBrightness);
|
|
29
|
-
expect(greenBrightness).toBeGreaterThan(blueBrightness);
|
|
30
|
-
expect(redBrightness).toBeGreaterThan(blueBrightness);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should calculate correct luminance values', () => {
|
|
34
|
-
// Pure red: 0.21 * 255 = 53.55
|
|
35
|
-
expect(calculateBrightness(255, 0, 0)).toBeCloseTo(53.55, 1);
|
|
36
|
-
// Pure green: 0.72 * 255 = 183.6
|
|
37
|
-
expect(calculateBrightness(0, 255, 0)).toBeCloseTo(183.6, 1);
|
|
38
|
-
// Pure blue: 0.07 * 255 = 17.85
|
|
39
|
-
expect(calculateBrightness(0, 0, 255)).toBeCloseTo(17.85, 1);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('should handle mid-gray', () => {
|
|
43
|
-
const gray = calculateBrightness(128, 128, 128);
|
|
44
|
-
// 128 * (0.21 + 0.72 + 0.07) = 128
|
|
45
|
-
expect(gray).toBe(128);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe('brightnessToChar', () => {
|
|
50
|
-
it('should return space for brightness 0', () => {
|
|
51
|
-
expect(brightnessToChar(0)).toBe(' ');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should return last character for brightness 255', () => {
|
|
55
|
-
expect(brightnessToChar(255)).toBe('@');
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('should map mid-brightness to middle character', () => {
|
|
59
|
-
// With ' .:-=+*#%@' (10 chars), brightness 127-128 should be around index 4-5
|
|
60
|
-
const char = brightnessToChar(127);
|
|
61
|
-
expect(['=', '+'].includes(char)).toBe(true);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should use custom character set', () => {
|
|
65
|
-
const customSet = ' abc';
|
|
66
|
-
expect(brightnessToChar(0, customSet)).toBe(' ');
|
|
67
|
-
expect(brightnessToChar(255, customSet)).toBe('c');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should handle two-character set', () => {
|
|
71
|
-
const binarySet = ' #';
|
|
72
|
-
expect(brightnessToChar(0, binarySet)).toBe(' ');
|
|
73
|
-
expect(brightnessToChar(127, binarySet)).toBe(' ');
|
|
74
|
-
expect(brightnessToChar(255, binarySet)).toBe('#');
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should clamp to valid range', () => {
|
|
78
|
-
// Even with extreme values, should not crash
|
|
79
|
-
expect(() => brightnessToChar(-10)).not.toThrow();
|
|
80
|
-
expect(() => brightnessToChar(300)).not.toThrow();
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe('DEFAULT_CHARACTERS', () => {
|
|
85
|
-
it('should be standard ASCII art character set', () => {
|
|
86
|
-
expect(DEFAULT_CHARACTERS).toBe(' .:-=+*#%@');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('should start with space', () => {
|
|
90
|
-
expect(DEFAULT_CHARACTERS[0]).toBe(' ');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('should have 10 characters', () => {
|
|
94
|
-
expect(DEFAULT_CHARACTERS.length).toBe(10);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
describe('DEFAULT_CONFIG', () => {
|
|
99
|
-
it('should have all required properties', () => {
|
|
100
|
-
expect(DEFAULT_CONFIG.characters).toBe(DEFAULT_CHARACTERS);
|
|
101
|
-
expect(DEFAULT_CONFIG.cellWidth).toBe(8);
|
|
102
|
-
expect(DEFAULT_CONFIG.cellHeight).toBe(12);
|
|
103
|
-
expect(DEFAULT_CONFIG.color).toBe('#ffffff');
|
|
104
|
-
expect(DEFAULT_CONFIG.backgroundColor).toBe('');
|
|
105
|
-
expect(DEFAULT_CONFIG.fontFamily).toBe('monospace');
|
|
106
|
-
expect(DEFAULT_CONFIG.animate).toBe(false);
|
|
107
|
-
expect(DEFAULT_CONFIG.fps).toBe(30);
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
describe('VERSION', () => {
|
|
112
|
-
it('should be a semver string', () => {
|
|
113
|
-
expect(VERSION).toMatch(/^\d+\.\d+\.\d+$/);
|
|
114
|
-
});
|
|
115
|
-
});
|