@autumnsgrove/gossamer 0.1.0 → 0.1.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/dist/characters.d.ts.map +1 -1
- package/dist/colors.d.ts +312 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +542 -0
- package/dist/index.js.map +1 -1
- package/dist/patterns.d.ts +119 -2
- package/dist/patterns.d.ts.map +1 -1
- package/dist/renderer.d.ts +27 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/svelte/index.js +9 -12
- package/dist/svelte/index.js.map +1 -1
- package/package.json +12 -3
- package/src/characters.ts +55 -0
- package/src/colors.ts +234 -0
- package/src/index.ts +35 -4
- package/src/patterns.ts +447 -3
- package/src/renderer.ts +161 -0
- package/src/svelte/GossamerClouds.svelte +6 -6
package/dist/index.js
CHANGED
|
@@ -16,6 +16,8 @@ class GossamerRenderer {
|
|
|
16
16
|
this.animationId = null;
|
|
17
17
|
this.lastFrameTime = 0;
|
|
18
18
|
this.isRunning = false;
|
|
19
|
+
this.charAtlas = null;
|
|
20
|
+
this.atlasCharacters = "";
|
|
19
21
|
const context = canvas.getContext("2d");
|
|
20
22
|
if (!context) {
|
|
21
23
|
throw new Error("Failed to get 2D rendering context");
|
|
@@ -27,6 +29,43 @@ class GossamerRenderer {
|
|
|
27
29
|
...config
|
|
28
30
|
};
|
|
29
31
|
this.setupCanvas();
|
|
32
|
+
this.buildCharacterAtlas();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build character texture atlas for fast rendering
|
|
36
|
+
* Pre-renders all characters to an offscreen canvas, then uses drawImage
|
|
37
|
+
* instead of fillText for 5-10x faster rendering
|
|
38
|
+
*/
|
|
39
|
+
buildCharacterAtlas() {
|
|
40
|
+
const { characters, cellWidth, cellHeight, color, fontFamily } = this.config;
|
|
41
|
+
if (this.atlasCharacters === characters && this.charAtlas) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const atlasWidth = characters.length * cellWidth;
|
|
45
|
+
const atlasHeight = cellHeight;
|
|
46
|
+
if (typeof OffscreenCanvas !== "undefined") {
|
|
47
|
+
this.charAtlas = new OffscreenCanvas(atlasWidth, atlasHeight);
|
|
48
|
+
} else {
|
|
49
|
+
this.charAtlas = document.createElement("canvas");
|
|
50
|
+
this.charAtlas.width = atlasWidth;
|
|
51
|
+
this.charAtlas.height = atlasHeight;
|
|
52
|
+
}
|
|
53
|
+
const ctx = this.charAtlas.getContext("2d");
|
|
54
|
+
if (!ctx) {
|
|
55
|
+
this.charAtlas = null;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
ctx.clearRect(0, 0, atlasWidth, atlasHeight);
|
|
59
|
+
ctx.fillStyle = color;
|
|
60
|
+
ctx.font = `${cellHeight}px ${fontFamily}`;
|
|
61
|
+
ctx.textBaseline = "top";
|
|
62
|
+
for (let i = 0; i < characters.length; i++) {
|
|
63
|
+
const char = characters[i];
|
|
64
|
+
if (char !== " ") {
|
|
65
|
+
ctx.fillText(char, i * cellWidth, 0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
this.atlasCharacters = characters;
|
|
30
69
|
}
|
|
31
70
|
/**
|
|
32
71
|
* Set up the canvas with optimal rendering settings
|
|
@@ -42,8 +81,13 @@ class GossamerRenderer {
|
|
|
42
81
|
* Update the renderer configuration
|
|
43
82
|
*/
|
|
44
83
|
updateConfig(config) {
|
|
84
|
+
const needsAtlasRebuild = config.characters !== void 0 || config.color !== void 0 || config.cellWidth !== void 0 || config.cellHeight !== void 0 || config.fontFamily !== void 0;
|
|
45
85
|
this.config = { ...this.config, ...config };
|
|
46
86
|
this.setupCanvas();
|
|
87
|
+
if (needsAtlasRebuild) {
|
|
88
|
+
this.atlasCharacters = "";
|
|
89
|
+
this.buildCharacterAtlas();
|
|
90
|
+
}
|
|
47
91
|
}
|
|
48
92
|
/**
|
|
49
93
|
* Resize the canvas to match new dimensions
|
|
@@ -135,6 +179,95 @@ class GossamerRenderer {
|
|
|
135
179
|
}
|
|
136
180
|
}
|
|
137
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* PERFORMANCE: Render from BrightnessBuffer using texture atlas
|
|
184
|
+
*
|
|
185
|
+
* Uses pre-rendered character sprites instead of fillText calls.
|
|
186
|
+
* 5-10x faster than renderFromBrightnessGrid for large canvases.
|
|
187
|
+
*
|
|
188
|
+
* @param buffer - BrightnessBuffer from fillBrightnessBuffer
|
|
189
|
+
*/
|
|
190
|
+
renderFromBuffer(buffer) {
|
|
191
|
+
const { characters, cellWidth, cellHeight } = this.config;
|
|
192
|
+
this.clear();
|
|
193
|
+
if (!this.charAtlas) {
|
|
194
|
+
this.ctx.fillStyle = this.config.color;
|
|
195
|
+
const charLen2 = characters.length - 1;
|
|
196
|
+
let idx2 = 0;
|
|
197
|
+
for (let row = 0; row < buffer.rows; row++) {
|
|
198
|
+
for (let col = 0; col < buffer.cols; col++) {
|
|
199
|
+
const brightness = buffer.data[idx2++];
|
|
200
|
+
const charIndex = brightness / 255 * charLen2 | 0;
|
|
201
|
+
const char = characters[Math.min(charIndex, charLen2)];
|
|
202
|
+
if (char !== " ") {
|
|
203
|
+
this.ctx.fillText(char, col * cellWidth, row * cellHeight);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const charLen = characters.length - 1;
|
|
210
|
+
let idx = 0;
|
|
211
|
+
for (let row = 0; row < buffer.rows; row++) {
|
|
212
|
+
const y = row * cellHeight;
|
|
213
|
+
for (let col = 0; col < buffer.cols; col++) {
|
|
214
|
+
const brightness = buffer.data[idx++];
|
|
215
|
+
const charIndex = brightness / 255 * charLen | 0;
|
|
216
|
+
if (charIndex === 0 && characters[0] === " ") {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
this.ctx.drawImage(
|
|
220
|
+
this.charAtlas,
|
|
221
|
+
charIndex * cellWidth,
|
|
222
|
+
0,
|
|
223
|
+
cellWidth,
|
|
224
|
+
cellHeight,
|
|
225
|
+
// source
|
|
226
|
+
col * cellWidth,
|
|
227
|
+
y,
|
|
228
|
+
cellWidth,
|
|
229
|
+
cellHeight
|
|
230
|
+
// destination
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* PERFORMANCE: Render brightness grid using atlas (legacy grid format)
|
|
237
|
+
*
|
|
238
|
+
* @param grid - 2D array of brightness values
|
|
239
|
+
*/
|
|
240
|
+
renderGridFast(grid) {
|
|
241
|
+
const { characters, cellWidth, cellHeight } = this.config;
|
|
242
|
+
this.clear();
|
|
243
|
+
if (!this.charAtlas) {
|
|
244
|
+
this.renderFromBrightnessGrid(grid);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const charLen = characters.length - 1;
|
|
248
|
+
for (let row = 0; row < grid.length; row++) {
|
|
249
|
+
const y = row * cellHeight;
|
|
250
|
+
const rowData = grid[row];
|
|
251
|
+
for (let col = 0; col < rowData.length; col++) {
|
|
252
|
+
const brightness = rowData[col];
|
|
253
|
+
const charIndex = brightness / 255 * charLen | 0;
|
|
254
|
+
if (charIndex === 0 && characters[0] === " ") {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
this.ctx.drawImage(
|
|
258
|
+
this.charAtlas,
|
|
259
|
+
charIndex * cellWidth,
|
|
260
|
+
0,
|
|
261
|
+
cellWidth,
|
|
262
|
+
cellHeight,
|
|
263
|
+
col * cellWidth,
|
|
264
|
+
y,
|
|
265
|
+
cellWidth,
|
|
266
|
+
cellHeight
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
138
271
|
/**
|
|
139
272
|
* Calculate average brightness for a cell region
|
|
140
273
|
*/
|
|
@@ -544,6 +677,97 @@ function seededNoise2D(x, y, seed = 0) {
|
|
|
544
677
|
const n = Math.sin(x * 12.9898 + y * 78.233 + seed) * 43758.5453;
|
|
545
678
|
return n - Math.floor(n);
|
|
546
679
|
}
|
|
680
|
+
function cloudsPattern(x, y, time, config = DEFAULT_PATTERN_CONFIG) {
|
|
681
|
+
const { frequency, amplitude, speed } = config;
|
|
682
|
+
const drift = time * speed * 0.02;
|
|
683
|
+
const nx = x * frequency * 0.5 + drift;
|
|
684
|
+
const ny = y * frequency * 0.5 + drift * 0.7;
|
|
685
|
+
const base = fbmNoise(nx, ny, 5, 0.6);
|
|
686
|
+
const detail = fbmNoise(nx * 2 + drift * 0.5, ny * 2 - drift * 0.3, 3, 0.5) * 0.3;
|
|
687
|
+
const combined = base + detail;
|
|
688
|
+
return Math.tanh(combined * 1.5) * amplitude;
|
|
689
|
+
}
|
|
690
|
+
function plasmaPattern(x, y, time, config = DEFAULT_PATTERN_CONFIG) {
|
|
691
|
+
const { frequency, amplitude, speed } = config;
|
|
692
|
+
const t = time * speed;
|
|
693
|
+
const v1 = Math.sin(x * frequency + t);
|
|
694
|
+
const v2 = Math.sin(y * frequency + t * 0.7);
|
|
695
|
+
const v3 = Math.sin((x + y) * frequency * 0.5 + t * 0.5);
|
|
696
|
+
const v4 = Math.sin(Math.sqrt(x * x + y * y) * frequency * 0.3 + t * 0.8);
|
|
697
|
+
const cx = x - 40;
|
|
698
|
+
const cy = y - 20;
|
|
699
|
+
const v5 = Math.sin(Math.atan2(cy, cx) * 3 + t * 0.4);
|
|
700
|
+
return (v1 + v2 + v3 + v4 + v5) / 5 * amplitude;
|
|
701
|
+
}
|
|
702
|
+
function vortexPattern(x, y, centerX, centerY, time, config = DEFAULT_PATTERN_CONFIG) {
|
|
703
|
+
const { frequency, amplitude, speed } = config;
|
|
704
|
+
const dx = x - centerX;
|
|
705
|
+
const dy = y - centerY;
|
|
706
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
707
|
+
const angle = Math.atan2(dy, dx);
|
|
708
|
+
const spiral = angle + distance * frequency * 0.1 - time * speed;
|
|
709
|
+
const turbulence = perlinNoise2D(distance * 0.1, time * speed * 0.5) * 0.3;
|
|
710
|
+
return (Math.sin(spiral * 3) + turbulence) * amplitude;
|
|
711
|
+
}
|
|
712
|
+
function matrixPattern(x, y, time, config = DEFAULT_PATTERN_CONFIG) {
|
|
713
|
+
const { frequency, amplitude, speed } = config;
|
|
714
|
+
const columnSeed = seededNoise2D(x, 0, 42);
|
|
715
|
+
const columnSpeed = 0.5 + columnSeed * 1.5;
|
|
716
|
+
const columnPhase = columnSeed * 100;
|
|
717
|
+
const fallPosition = (y * frequency + time * speed * columnSpeed + columnPhase) % 20;
|
|
718
|
+
const headBrightness = fallPosition < 1 ? 1 : 0;
|
|
719
|
+
const trailLength = 8;
|
|
720
|
+
const trailBrightness = fallPosition < trailLength ? Math.pow(1 - fallPosition / trailLength, 2) : 0;
|
|
721
|
+
const flicker = seededNoise2D(x, Math.floor(time * 10), y) * 0.2;
|
|
722
|
+
const value = Math.max(headBrightness, trailBrightness) + flicker;
|
|
723
|
+
return (value * 2 - 1) * amplitude;
|
|
724
|
+
}
|
|
725
|
+
function gradientPattern(x, y, cols, rows, time, config = DEFAULT_PATTERN_CONFIG) {
|
|
726
|
+
const { frequency, amplitude, speed } = config;
|
|
727
|
+
const nx = x / cols;
|
|
728
|
+
const ny = y / rows;
|
|
729
|
+
const angle = time * speed * 0.2;
|
|
730
|
+
const cos = Math.cos(angle);
|
|
731
|
+
const sin = Math.sin(angle);
|
|
732
|
+
const rotated = nx * cos + ny * sin;
|
|
733
|
+
const distortion = Math.sin(ny * Math.PI * 2 * frequency + time * speed) * 0.1;
|
|
734
|
+
const value = (rotated + distortion) * 2 - 1;
|
|
735
|
+
return Math.sin(value * Math.PI) * amplitude;
|
|
736
|
+
}
|
|
737
|
+
function diamondPattern(x, y, time, config = DEFAULT_PATTERN_CONFIG) {
|
|
738
|
+
const { frequency, amplitude, speed } = config;
|
|
739
|
+
const t = time * speed;
|
|
740
|
+
const wave1 = Math.sin((Math.abs(x - 40) + Math.abs(y - 20)) * frequency + t);
|
|
741
|
+
const wave2 = Math.sin((Math.abs(x - 40) - Math.abs(y - 20)) * frequency * 0.7 - t * 0.8);
|
|
742
|
+
const angle = t * 0.1;
|
|
743
|
+
const rx = x * Math.cos(angle) - y * Math.sin(angle);
|
|
744
|
+
const ry = x * Math.sin(angle) + y * Math.cos(angle);
|
|
745
|
+
const wave3 = Math.sin((Math.abs(rx) + Math.abs(ry)) * frequency * 0.5 + t * 0.5);
|
|
746
|
+
return (wave1 + wave2 + wave3) / 3 * amplitude;
|
|
747
|
+
}
|
|
748
|
+
function fractalPattern(x, y, cols, rows, time, config = DEFAULT_PATTERN_CONFIG) {
|
|
749
|
+
const { frequency, amplitude, speed } = config;
|
|
750
|
+
const scale = 3.5 * frequency;
|
|
751
|
+
const zx = x / cols * scale - scale / 2 + Math.sin(time * speed * 0.1) * 0.2;
|
|
752
|
+
const zy = y / rows * scale - scale / 2 + Math.cos(time * speed * 0.1) * 0.2;
|
|
753
|
+
const cx = -0.7 + Math.sin(time * speed * 0.05) * 0.1;
|
|
754
|
+
const cy = 0.27 + Math.cos(time * speed * 0.07) * 0.1;
|
|
755
|
+
let zrx = zx;
|
|
756
|
+
let zry = zy;
|
|
757
|
+
const maxIter = 20;
|
|
758
|
+
let iter = 0;
|
|
759
|
+
while (zrx * zrx + zry * zry < 4 && iter < maxIter) {
|
|
760
|
+
const tmp = zrx * zrx - zry * zry + cx;
|
|
761
|
+
zry = 2 * zrx * zry + cy;
|
|
762
|
+
zrx = tmp;
|
|
763
|
+
iter++;
|
|
764
|
+
}
|
|
765
|
+
if (iter === maxIter) {
|
|
766
|
+
return -1 * amplitude;
|
|
767
|
+
}
|
|
768
|
+
const smooth = iter - Math.log2(Math.log2(zrx * zrx + zry * zry));
|
|
769
|
+
return (smooth / maxIter * 2 - 1) * amplitude;
|
|
770
|
+
}
|
|
547
771
|
function generateBrightnessGrid(cols, rows, pattern, time = 0, config = DEFAULT_PATTERN_CONFIG) {
|
|
548
772
|
const grid = [];
|
|
549
773
|
const { frequency, amplitude, speed } = config;
|
|
@@ -573,6 +797,29 @@ function generateBrightnessGrid(cols, rows, pattern, time = 0, config = DEFAULT_
|
|
|
573
797
|
value = ripplePattern(col, row, cols / 2, rows / 2, time, config);
|
|
574
798
|
break;
|
|
575
799
|
case "static":
|
|
800
|
+
value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;
|
|
801
|
+
break;
|
|
802
|
+
case "clouds":
|
|
803
|
+
value = cloudsPattern(col, row, time, config);
|
|
804
|
+
break;
|
|
805
|
+
case "plasma":
|
|
806
|
+
value = plasmaPattern(col, row, time, config);
|
|
807
|
+
break;
|
|
808
|
+
case "vortex":
|
|
809
|
+
value = vortexPattern(col, row, cols / 2, rows / 2, time, config);
|
|
810
|
+
break;
|
|
811
|
+
case "matrix":
|
|
812
|
+
value = matrixPattern(col, row, time, config);
|
|
813
|
+
break;
|
|
814
|
+
case "gradient":
|
|
815
|
+
value = gradientPattern(col, row, cols, rows, time, config);
|
|
816
|
+
break;
|
|
817
|
+
case "diamond":
|
|
818
|
+
value = diamondPattern(col, row, time, config);
|
|
819
|
+
break;
|
|
820
|
+
case "fractal":
|
|
821
|
+
value = fractalPattern(col, row, cols, rows, time, config);
|
|
822
|
+
break;
|
|
576
823
|
default:
|
|
577
824
|
value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;
|
|
578
825
|
break;
|
|
@@ -607,6 +854,77 @@ function gridToImageData(grid, cellWidth, cellHeight) {
|
|
|
607
854
|
}
|
|
608
855
|
return new ImageData(data, width, height);
|
|
609
856
|
}
|
|
857
|
+
function createBrightnessBuffer(cols, rows) {
|
|
858
|
+
return {
|
|
859
|
+
data: new Uint8Array(cols * rows),
|
|
860
|
+
cols,
|
|
861
|
+
rows
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
function fillBrightnessBuffer(buffer, pattern, time = 0, config = DEFAULT_PATTERN_CONFIG) {
|
|
865
|
+
const { data, cols, rows } = buffer;
|
|
866
|
+
const { frequency, amplitude, speed } = config;
|
|
867
|
+
let idx = 0;
|
|
868
|
+
for (let row = 0; row < rows; row++) {
|
|
869
|
+
for (let col = 0; col < cols; col++) {
|
|
870
|
+
let value;
|
|
871
|
+
switch (pattern) {
|
|
872
|
+
case "perlin":
|
|
873
|
+
value = perlinNoise2D(
|
|
874
|
+
col * frequency + time * speed * 0.1,
|
|
875
|
+
row * frequency + time * speed * 0.05
|
|
876
|
+
);
|
|
877
|
+
break;
|
|
878
|
+
case "fbm":
|
|
879
|
+
value = fbmNoise(
|
|
880
|
+
col * frequency + time * speed * 0.1,
|
|
881
|
+
row * frequency + time * speed * 0.05,
|
|
882
|
+
4,
|
|
883
|
+
0.5
|
|
884
|
+
);
|
|
885
|
+
break;
|
|
886
|
+
case "waves":
|
|
887
|
+
value = wavePattern(col, row, time, config);
|
|
888
|
+
break;
|
|
889
|
+
case "ripple":
|
|
890
|
+
value = ripplePattern(col, row, cols / 2, rows / 2, time, config);
|
|
891
|
+
break;
|
|
892
|
+
case "static":
|
|
893
|
+
value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;
|
|
894
|
+
break;
|
|
895
|
+
case "clouds":
|
|
896
|
+
value = cloudsPattern(col, row, time, config);
|
|
897
|
+
break;
|
|
898
|
+
case "plasma":
|
|
899
|
+
value = plasmaPattern(col, row, time, config);
|
|
900
|
+
break;
|
|
901
|
+
case "vortex":
|
|
902
|
+
value = vortexPattern(col, row, cols / 2, rows / 2, time, config);
|
|
903
|
+
break;
|
|
904
|
+
case "matrix":
|
|
905
|
+
value = matrixPattern(col, row, time, config);
|
|
906
|
+
break;
|
|
907
|
+
case "gradient":
|
|
908
|
+
value = gradientPattern(col, row, cols, rows, time, config);
|
|
909
|
+
break;
|
|
910
|
+
case "diamond":
|
|
911
|
+
value = diamondPattern(col, row, time, config);
|
|
912
|
+
break;
|
|
913
|
+
case "fractal":
|
|
914
|
+
value = fractalPattern(col, row, cols, rows, time, config);
|
|
915
|
+
break;
|
|
916
|
+
default:
|
|
917
|
+
value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;
|
|
918
|
+
break;
|
|
919
|
+
}
|
|
920
|
+
const normalized = (value + 1) * 0.5 * amplitude;
|
|
921
|
+
data[idx++] = normalized * 255 | 0;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function getBufferValue(buffer, col, row) {
|
|
926
|
+
return buffer.data[row * buffer.cols + col];
|
|
927
|
+
}
|
|
610
928
|
const CHARACTER_SETS = {
|
|
611
929
|
standard: {
|
|
612
930
|
name: "Standard",
|
|
@@ -679,6 +997,53 @@ const CHARACTER_SETS = {
|
|
|
679
997
|
description: "Mathematical symbols",
|
|
680
998
|
characters: " +-×÷=≠≈∞",
|
|
681
999
|
bestFor: ["abstract patterns", "tech themes", "decorative"]
|
|
1000
|
+
},
|
|
1001
|
+
// ==========================================================================
|
|
1002
|
+
// GLASS-OPTIMIZED CHARACTER SETS
|
|
1003
|
+
// Designed for subtle overlays on Glass components
|
|
1004
|
+
// More characters = more visible gradations
|
|
1005
|
+
// ==========================================================================
|
|
1006
|
+
"glass-dots": {
|
|
1007
|
+
name: "Glass Dots",
|
|
1008
|
+
description: "Soft dot gradations for glass overlays",
|
|
1009
|
+
characters: " ·∘∙○•●",
|
|
1010
|
+
bestFor: ["glass overlays", "subtle backgrounds", "mist effects"]
|
|
1011
|
+
},
|
|
1012
|
+
"glass-mist": {
|
|
1013
|
+
name: "Glass Mist",
|
|
1014
|
+
description: "Ethereal mist effect for glass",
|
|
1015
|
+
characters: " .·∙•◦○◉●",
|
|
1016
|
+
bestFor: ["glass overlays", "fog effects", "ambient backgrounds"]
|
|
1017
|
+
},
|
|
1018
|
+
"glass-dust": {
|
|
1019
|
+
name: "Glass Dust",
|
|
1020
|
+
description: "Floating dust particles",
|
|
1021
|
+
characters: " ˙·∘°•◦○",
|
|
1022
|
+
bestFor: ["glass overlays", "particle effects", "light scatter"]
|
|
1023
|
+
},
|
|
1024
|
+
"glass-soft": {
|
|
1025
|
+
name: "Glass Soft",
|
|
1026
|
+
description: "Soft block gradations for glass",
|
|
1027
|
+
characters: " ·░▒▓",
|
|
1028
|
+
bestFor: ["glass overlays", "soft gradients", "frosted effect"]
|
|
1029
|
+
},
|
|
1030
|
+
"glass-sparkle": {
|
|
1031
|
+
name: "Glass Sparkle",
|
|
1032
|
+
description: "Subtle sparkles for glass",
|
|
1033
|
+
characters: " ·.✧✦✫★",
|
|
1034
|
+
bestFor: ["glass overlays", "highlight effects", "magical themes"]
|
|
1035
|
+
},
|
|
1036
|
+
"glass-wave": {
|
|
1037
|
+
name: "Glass Wave",
|
|
1038
|
+
description: "Flowing wave patterns for glass",
|
|
1039
|
+
characters: " .~∼≈≋",
|
|
1040
|
+
bestFor: ["glass overlays", "water effects", "flowing motion"]
|
|
1041
|
+
},
|
|
1042
|
+
"glass-organic": {
|
|
1043
|
+
name: "Glass Organic",
|
|
1044
|
+
description: "Natural, organic feel for glass",
|
|
1045
|
+
characters: " .·:;∘○◦•●",
|
|
1046
|
+
bestFor: ["glass overlays", "nature themes", "grove aesthetic"]
|
|
682
1047
|
}
|
|
683
1048
|
};
|
|
684
1049
|
function getCharacterSet(name) {
|
|
@@ -707,6 +1072,162 @@ function validateCharacterSet(characters) {
|
|
|
707
1072
|
function invertCharacters(characters) {
|
|
708
1073
|
return characters.split("").reverse().join("");
|
|
709
1074
|
}
|
|
1075
|
+
const GROVE_GREEN = {
|
|
1076
|
+
50: { hex: "#f0fdf4", name: "Grove Green 50", glassOpacity: 0.3 },
|
|
1077
|
+
100: { hex: "#dcfce7", name: "Grove Green 100", glassOpacity: 0.25 },
|
|
1078
|
+
200: { hex: "#bbf7d0", name: "Grove Green 200", glassOpacity: 0.2 },
|
|
1079
|
+
300: { hex: "#86efac", name: "Grove Green 300", glassOpacity: 0.18 },
|
|
1080
|
+
400: { hex: "#4ade80", name: "Grove Green 400", glassOpacity: 0.15 },
|
|
1081
|
+
500: { hex: "#22c55e", name: "Grove Green 500", glassOpacity: 0.12 },
|
|
1082
|
+
600: { hex: "#16a34a", name: "Grove Green 600", glassOpacity: 0.1 },
|
|
1083
|
+
700: { hex: "#15803d", name: "Grove Green 700", glassOpacity: 0.1 },
|
|
1084
|
+
800: { hex: "#166534", name: "Grove Green 800", glassOpacity: 0.08 },
|
|
1085
|
+
900: { hex: "#14532d", name: "Grove Green 900", glassOpacity: 0.08 }
|
|
1086
|
+
};
|
|
1087
|
+
const CREAM = {
|
|
1088
|
+
50: { hex: "#fefdfb", name: "Cream 50", glassOpacity: 0.4 },
|
|
1089
|
+
100: { hex: "#fdfcf8", name: "Cream 100", glassOpacity: 0.35 },
|
|
1090
|
+
200: { hex: "#faf8f3", name: "Cream 200", glassOpacity: 0.3 },
|
|
1091
|
+
300: { hex: "#f5f2ea", name: "Cream 300", glassOpacity: 0.25 },
|
|
1092
|
+
400: { hex: "#ede9de", name: "Cream 400", glassOpacity: 0.2 },
|
|
1093
|
+
500: { hex: "#e2ddd0", name: "Cream 500", glassOpacity: 0.18 },
|
|
1094
|
+
600: { hex: "#d4cec0", name: "Cream 600", glassOpacity: 0.15 },
|
|
1095
|
+
700: { hex: "#c4bdb0", name: "Cream 700", glassOpacity: 0.12 },
|
|
1096
|
+
800: { hex: "#b0a99c", name: "Cream 800", glassOpacity: 0.1 },
|
|
1097
|
+
900: { hex: "#9a9387", name: "Cream 900", glassOpacity: 0.08 }
|
|
1098
|
+
};
|
|
1099
|
+
const BARK = {
|
|
1100
|
+
50: { hex: "#faf7f5", name: "Bark 50", glassOpacity: 0.3 },
|
|
1101
|
+
100: { hex: "#f0ebe6", name: "Bark 100", glassOpacity: 0.25 },
|
|
1102
|
+
200: { hex: "#e0d5cc", name: "Bark 200", glassOpacity: 0.2 },
|
|
1103
|
+
300: { hex: "#ccb59c", name: "Bark 300", glassOpacity: 0.18 },
|
|
1104
|
+
400: { hex: "#b89a7a", name: "Bark 400", glassOpacity: 0.15 },
|
|
1105
|
+
500: { hex: "#a57c5a", name: "Bark 500", glassOpacity: 0.12 },
|
|
1106
|
+
600: { hex: "#8a6344", name: "Bark 600", glassOpacity: 0.1 },
|
|
1107
|
+
700: { hex: "#6f4d39", name: "Bark 700", glassOpacity: 0.1 },
|
|
1108
|
+
800: { hex: "#553a2a", name: "Bark 800", glassOpacity: 0.08 },
|
|
1109
|
+
900: { hex: "#3d2914", name: "Bark 900", glassOpacity: 0.06 }
|
|
1110
|
+
};
|
|
1111
|
+
const STATUS = {
|
|
1112
|
+
success: { hex: "#22c55e", name: "Success", glassOpacity: 0.12 },
|
|
1113
|
+
warning: { hex: "#f59e0b", name: "Warning", glassOpacity: 0.12 },
|
|
1114
|
+
error: { hex: "#dc2626", name: "Error", glassOpacity: 0.1 },
|
|
1115
|
+
info: { hex: "#0ea5e9", name: "Info", glassOpacity: 0.12 }
|
|
1116
|
+
};
|
|
1117
|
+
const GROVE_COLORS = {
|
|
1118
|
+
// Greens
|
|
1119
|
+
grove: GROVE_GREEN[500].hex,
|
|
1120
|
+
"grove-light": GROVE_GREEN[300].hex,
|
|
1121
|
+
"grove-dark": GROVE_GREEN[700].hex,
|
|
1122
|
+
"grove-muted": GROVE_GREEN[400].hex,
|
|
1123
|
+
// Creams
|
|
1124
|
+
cream: CREAM[50].hex,
|
|
1125
|
+
"cream-warm": CREAM[200].hex,
|
|
1126
|
+
"cream-deep": CREAM[500].hex,
|
|
1127
|
+
// Barks
|
|
1128
|
+
bark: BARK[900].hex,
|
|
1129
|
+
"bark-light": BARK[500].hex,
|
|
1130
|
+
"bark-medium": BARK[700].hex,
|
|
1131
|
+
// Utility
|
|
1132
|
+
white: "#ffffff",
|
|
1133
|
+
black: "#000000",
|
|
1134
|
+
transparent: "transparent"
|
|
1135
|
+
};
|
|
1136
|
+
const GLASS_SCHEMES = {
|
|
1137
|
+
// Light mode schemes (on light backgrounds)
|
|
1138
|
+
"grove-mist": {
|
|
1139
|
+
color: GROVE_GREEN[500].hex,
|
|
1140
|
+
background: "transparent",
|
|
1141
|
+
opacity: 0.12,
|
|
1142
|
+
description: "Subtle green mist for light glass"
|
|
1143
|
+
},
|
|
1144
|
+
"cream-haze": {
|
|
1145
|
+
color: CREAM[600].hex,
|
|
1146
|
+
background: "transparent",
|
|
1147
|
+
opacity: 0.15,
|
|
1148
|
+
description: "Warm cream haze for cozy glass"
|
|
1149
|
+
},
|
|
1150
|
+
"bark-shadow": {
|
|
1151
|
+
color: BARK[700].hex,
|
|
1152
|
+
background: "transparent",
|
|
1153
|
+
opacity: 0.08,
|
|
1154
|
+
description: "Soft earth shadow for depth"
|
|
1155
|
+
},
|
|
1156
|
+
// Dark mode schemes (on dark backgrounds)
|
|
1157
|
+
"grove-glow": {
|
|
1158
|
+
color: GROVE_GREEN[400].hex,
|
|
1159
|
+
background: "#1a1915",
|
|
1160
|
+
opacity: 0.15,
|
|
1161
|
+
description: "Glowing green for dark glass"
|
|
1162
|
+
},
|
|
1163
|
+
"cream-dust": {
|
|
1164
|
+
color: CREAM[300].hex,
|
|
1165
|
+
background: "#1a1915",
|
|
1166
|
+
opacity: 0.1,
|
|
1167
|
+
description: "Dusty cream particles in dark"
|
|
1168
|
+
},
|
|
1169
|
+
"moonlight": {
|
|
1170
|
+
color: "#e2e8f0",
|
|
1171
|
+
background: "#1a1915",
|
|
1172
|
+
opacity: 0.08,
|
|
1173
|
+
description: "Cool moonlight glow"
|
|
1174
|
+
},
|
|
1175
|
+
// Accent schemes
|
|
1176
|
+
"spring-fresh": {
|
|
1177
|
+
color: GROVE_GREEN[300].hex,
|
|
1178
|
+
background: "transparent",
|
|
1179
|
+
opacity: 0.18,
|
|
1180
|
+
description: "Fresh spring green overlay"
|
|
1181
|
+
},
|
|
1182
|
+
"autumn-warm": {
|
|
1183
|
+
color: "#d97706",
|
|
1184
|
+
background: "transparent",
|
|
1185
|
+
opacity: 0.1,
|
|
1186
|
+
description: "Warm autumn amber tones"
|
|
1187
|
+
},
|
|
1188
|
+
"winter-frost": {
|
|
1189
|
+
color: "#93c5fd",
|
|
1190
|
+
background: "transparent",
|
|
1191
|
+
opacity: 0.12,
|
|
1192
|
+
description: "Cool frost blue overlay"
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1195
|
+
function getGroveColor(name) {
|
|
1196
|
+
if (name in GROVE_COLORS) {
|
|
1197
|
+
return GROVE_COLORS[name];
|
|
1198
|
+
}
|
|
1199
|
+
if (name.startsWith("#")) {
|
|
1200
|
+
return name;
|
|
1201
|
+
}
|
|
1202
|
+
return GROVE_COLORS.grove;
|
|
1203
|
+
}
|
|
1204
|
+
function getGlassScheme(name) {
|
|
1205
|
+
if (name in GLASS_SCHEMES) {
|
|
1206
|
+
const scheme = GLASS_SCHEMES[name];
|
|
1207
|
+
return {
|
|
1208
|
+
color: scheme.color,
|
|
1209
|
+
background: scheme.background,
|
|
1210
|
+
opacity: scheme.opacity
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
return {
|
|
1214
|
+
color: GLASS_SCHEMES["grove-mist"].color,
|
|
1215
|
+
background: GLASS_SCHEMES["grove-mist"].background,
|
|
1216
|
+
opacity: GLASS_SCHEMES["grove-mist"].opacity
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
function getGroveColorNames() {
|
|
1220
|
+
return Object.keys(GROVE_COLORS);
|
|
1221
|
+
}
|
|
1222
|
+
function getGlassSchemeNames() {
|
|
1223
|
+
return Object.keys(GLASS_SCHEMES);
|
|
1224
|
+
}
|
|
1225
|
+
function hexToRgba(hex, opacity) {
|
|
1226
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
1227
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
1228
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
1229
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
1230
|
+
}
|
|
710
1231
|
function createAnimationLoop(options) {
|
|
711
1232
|
const { fps = 30, onStart, onStop, onFrame } = options;
|
|
712
1233
|
const state = {
|
|
@@ -1244,11 +1765,17 @@ function brightnessToChar(brightness, characters = DEFAULT_CHARACTERS) {
|
|
|
1244
1765
|
}
|
|
1245
1766
|
const VERSION = "0.1.0";
|
|
1246
1767
|
export {
|
|
1768
|
+
BARK,
|
|
1247
1769
|
CHARACTER_SETS,
|
|
1770
|
+
CREAM,
|
|
1248
1771
|
DEFAULT_CHARACTERS,
|
|
1249
1772
|
DEFAULT_CONFIG,
|
|
1250
1773
|
DEFAULT_PATTERN_CONFIG,
|
|
1774
|
+
GLASS_SCHEMES,
|
|
1775
|
+
GROVE_COLORS,
|
|
1776
|
+
GROVE_GREEN,
|
|
1251
1777
|
GossamerRenderer,
|
|
1778
|
+
STATUS,
|
|
1252
1779
|
VERSION,
|
|
1253
1780
|
adjustBrightness,
|
|
1254
1781
|
adjustContrast,
|
|
@@ -1258,7 +1785,9 @@ export {
|
|
|
1258
1785
|
calculateFPS,
|
|
1259
1786
|
cancelIdleCallback,
|
|
1260
1787
|
clearCanvas,
|
|
1788
|
+
cloudsPattern,
|
|
1261
1789
|
createAnimationLoop,
|
|
1790
|
+
createBrightnessBuffer,
|
|
1262
1791
|
createCanvas,
|
|
1263
1792
|
createCharacterSet,
|
|
1264
1793
|
createFPSCounter,
|
|
@@ -1266,18 +1795,28 @@ export {
|
|
|
1266
1795
|
createResizeObserver,
|
|
1267
1796
|
createVisibilityObserver,
|
|
1268
1797
|
debounce,
|
|
1798
|
+
diamondPattern,
|
|
1269
1799
|
easings,
|
|
1270
1800
|
extractBrightness,
|
|
1271
1801
|
fbmNoise,
|
|
1802
|
+
fillBrightnessBuffer,
|
|
1803
|
+
fractalPattern,
|
|
1272
1804
|
generateBrightnessGrid,
|
|
1805
|
+
getBufferValue,
|
|
1273
1806
|
getCharacterSet,
|
|
1274
1807
|
getCharacterSetNames,
|
|
1275
1808
|
getCharacters,
|
|
1276
1809
|
getDevicePixelRatio,
|
|
1810
|
+
getGlassScheme,
|
|
1811
|
+
getGlassSchemeNames,
|
|
1812
|
+
getGroveColor,
|
|
1813
|
+
getGroveColorNames,
|
|
1277
1814
|
getImageData,
|
|
1278
1815
|
getRecommendedFPS,
|
|
1816
|
+
gradientPattern,
|
|
1279
1817
|
gridToImageData,
|
|
1280
1818
|
hexToRgb,
|
|
1819
|
+
hexToRgba,
|
|
1281
1820
|
imageToPixelData,
|
|
1282
1821
|
invertCharacters,
|
|
1283
1822
|
invertColors,
|
|
@@ -1287,10 +1826,12 @@ export {
|
|
|
1287
1826
|
isOffscreenCanvasSupported,
|
|
1288
1827
|
loadAndScaleImage,
|
|
1289
1828
|
loadImage,
|
|
1829
|
+
matrixPattern,
|
|
1290
1830
|
measureTextWidth,
|
|
1291
1831
|
onReducedMotionChange,
|
|
1292
1832
|
optimizeContext,
|
|
1293
1833
|
perlinNoise2D,
|
|
1834
|
+
plasmaPattern,
|
|
1294
1835
|
prefersReducedMotion,
|
|
1295
1836
|
requestIdleCallback,
|
|
1296
1837
|
resizeCanvasToContainer,
|
|
@@ -1304,6 +1845,7 @@ export {
|
|
|
1304
1845
|
throttle,
|
|
1305
1846
|
toGrayscale,
|
|
1306
1847
|
validateCharacterSet,
|
|
1848
|
+
vortexPattern,
|
|
1307
1849
|
wavePattern
|
|
1308
1850
|
};
|
|
1309
1851
|
//# sourceMappingURL=index.js.map
|