@iconoma-icons/collection 1.0.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/dist/index.js ADDED
@@ -0,0 +1,835 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_COLORS: () => DEFAULT_COLORS,
24
+ DEFAULT_PALETTE: () => DEFAULT_PALETTE,
25
+ DEFAULT_PARAMETERS: () => DEFAULT_PARAMETERS,
26
+ gradient: () => gradient,
27
+ inkblot: () => inkblot,
28
+ mondrian: () => mondrian,
29
+ mosaic: () => mosaic,
30
+ paletteNames: () => paletteNames,
31
+ palettes: () => palettes,
32
+ pixel: () => pixel,
33
+ pixelated: () => pixelated,
34
+ polycon: () => polycon,
35
+ waves: () => waves
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/types.ts
40
+ var DEFAULT_PARAMETERS = {
41
+ pixel: {
42
+ seedDensity: 0.45,
43
+ generations: 3,
44
+ maxCells: 15,
45
+ marginSize: 0.15
46
+ },
47
+ pixelated: {
48
+ blockSize: 8,
49
+ patternType: "random",
50
+ colorVariation: 0.5,
51
+ colorsPerIcon: 4
52
+ },
53
+ mondrian: {
54
+ divisionCount: 10,
55
+ lineThickness: 3,
56
+ balance: 0.5,
57
+ colorsPerIcon: 4
58
+ },
59
+ gradient: {
60
+ waveComplexity: 3,
61
+ direction: "diagonal",
62
+ blendSmoothness: 0.7
63
+ },
64
+ mosaic: {
65
+ tileCount: 80,
66
+ tileSizeVariation: 0.5,
67
+ gapSize: 1,
68
+ colorsPerIcon: 4
69
+ },
70
+ waves: {
71
+ waveCount: 4,
72
+ amplitude: 0.25,
73
+ frequency: 3,
74
+ direction: "horizontal"
75
+ },
76
+ polycon: {
77
+ gridSize: 2,
78
+ emptyProbability: 0.15,
79
+ fullSquareProbability: 0.1,
80
+ colorsPerIcon: 3
81
+ },
82
+ inkblot: {
83
+ blobCount: 3,
84
+ spread: 0.5,
85
+ symmetry: "vertical",
86
+ centered: false
87
+ }
88
+ };
89
+
90
+ // src/utils.ts
91
+ function getLuminance(color) {
92
+ const rgb = parseColor(color);
93
+ const [r, g, b] = rgb.map((c) => {
94
+ c = c / 255;
95
+ return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
96
+ });
97
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
98
+ }
99
+ function parseColor(color) {
100
+ if (color.startsWith("hsl")) {
101
+ const matches = color.match(/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/);
102
+ if (matches) {
103
+ const h = parseInt(matches[1], 10) / 360;
104
+ const s = parseInt(matches[2], 10) / 100;
105
+ const l = parseInt(matches[3], 10) / 100;
106
+ return hslToRgb(h, s, l);
107
+ }
108
+ }
109
+ const hex = color.replace("#", "");
110
+ return [
111
+ parseInt(hex.substring(0, 2), 16),
112
+ parseInt(hex.substring(2, 4), 16),
113
+ parseInt(hex.substring(4, 6), 16)
114
+ ];
115
+ }
116
+ function hslToRgb(h, s, l) {
117
+ let r = 0, g = 0, b = 0;
118
+ if (s === 0) {
119
+ r = g = b = l;
120
+ } else {
121
+ const hue2rgb = (p2, q2, t) => {
122
+ if (t < 0) t += 1;
123
+ if (t > 1) t -= 1;
124
+ if (t < 1 / 6) return p2 + (q2 - p2) * 6 * t;
125
+ if (t < 1 / 2) return q2;
126
+ if (t < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - t) * 6;
127
+ return p2;
128
+ };
129
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
130
+ const p = 2 * l - q;
131
+ r = hue2rgb(p, q, h + 1 / 3);
132
+ g = hue2rgb(p, q, h);
133
+ b = hue2rgb(p, q, h - 1 / 3);
134
+ }
135
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
136
+ }
137
+ function darkenColor(color, amount = 0.3) {
138
+ const rgb = parseColor(color);
139
+ return `rgb(${rgb.map((c) => Math.round(c * (1 - amount))).join(",")})`;
140
+ }
141
+ function lightenColor(color, amount = 0.3) {
142
+ const rgb = parseColor(color);
143
+ return `rgb(${rgb.map((c) => Math.min(255, Math.round(c + (255 - c) * amount))).join(",")})`;
144
+ }
145
+
146
+ // src/pixel.ts
147
+ var pixel = (rng, options) => {
148
+ const size = options.size || 500;
149
+ const colors = options.colors || [];
150
+ let finalColors = [...colors];
151
+ const p = options.styleOptions || DEFAULT_PARAMETERS.pixel;
152
+ if (p && p.colorsPerIcon) {
153
+ const shuffled = rng.shuffle([...colors]);
154
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
155
+ } else if (p && p.colorCount) {
156
+ const shuffled = rng.shuffle([...colors]);
157
+ finalColors = shuffled.slice(0, p.colorCount);
158
+ }
159
+ const config = { styleParameters: { pixel: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
160
+ const params = { ...DEFAULT_PARAMETERS.pixel, ...options.styleOptions || {} };
161
+ const gridSize = 7;
162
+ const halfGrid = 4;
163
+ function countNeighbors(grid2, row, col) {
164
+ let count = 0;
165
+ for (let dr = -1; dr <= 1; dr++) {
166
+ for (let dc = -1; dc <= 1; dc++) {
167
+ if (dr === 0 && dc === 0) continue;
168
+ const nr = row + dr;
169
+ const nc = col + dc;
170
+ if (nr >= 0 && nr < gridSize && nc >= 0 && nc < halfGrid) {
171
+ if (grid2[nr][nc]) count++;
172
+ }
173
+ }
174
+ }
175
+ return count;
176
+ }
177
+ function runGeneration(grid2) {
178
+ const newGrid = Array(gridSize).fill(0).map(() => Array(halfGrid).fill(false));
179
+ for (let row = 0; row < gridSize; row++) {
180
+ for (let col = 0; col < halfGrid; col++) {
181
+ const neighbors = countNeighbors(grid2, row, col);
182
+ const isAlive = grid2[row][col];
183
+ if (!isAlive) {
184
+ newGrid[row][col] = neighbors === 3;
185
+ } else {
186
+ newGrid[row][col] = neighbors === 2 || neighbors === 3 || neighbors === 4;
187
+ }
188
+ }
189
+ }
190
+ return newGrid;
191
+ }
192
+ function countAliveCells(grid2) {
193
+ let count = 0;
194
+ for (let row = 0; row < gridSize; row++) {
195
+ for (let col = 0; col < halfGrid; col++) {
196
+ if (grid2[row][col]) count++;
197
+ }
198
+ }
199
+ return count;
200
+ }
201
+ let grid = [];
202
+ let attempts = 0;
203
+ while (attempts < 50) {
204
+ grid = Array(gridSize).fill(0).map(
205
+ () => Array(halfGrid).fill(0).map(() => rng.random() < params.seedDensity)
206
+ );
207
+ for (let gen = 0; gen < params.generations; gen++) {
208
+ grid = runGeneration(grid);
209
+ }
210
+ const cellCount = countAliveCells(grid);
211
+ if (cellCount >= 8 && cellCount <= params.maxCells) {
212
+ break;
213
+ }
214
+ attempts++;
215
+ }
216
+ const fullGrid = Array(gridSize).fill(0).map(() => Array(gridSize).fill(false));
217
+ for (let row = 0; row < gridSize; row++) {
218
+ for (let col = 0; col < halfGrid; col++) {
219
+ fullGrid[row][col] = grid[row][col];
220
+ const mirrorCol = gridSize - 1 - col;
221
+ fullGrid[row][mirrorCol] = grid[row][col];
222
+ }
223
+ }
224
+ let minRow = gridSize, maxRow = -1;
225
+ let minCol = gridSize, maxCol = -1;
226
+ for (let row = 0; row < gridSize; row++) {
227
+ for (let col = 0; col < gridSize; col++) {
228
+ if (fullGrid[row][col]) {
229
+ minRow = Math.min(minRow, row);
230
+ maxRow = Math.max(maxRow, row);
231
+ minCol = Math.min(minCol, col);
232
+ maxCol = Math.max(maxCol, col);
233
+ }
234
+ }
235
+ }
236
+ const shapeWidth = maxCol - minCol + 1;
237
+ const shapeHeight = maxRow - minRow + 1;
238
+ const margin = size * params.marginSize;
239
+ const availableSize = size - margin * 2;
240
+ const cellSize = Math.ceil(availableSize / Math.max(shapeWidth, shapeHeight));
241
+ const totalWidth = shapeWidth * cellSize;
242
+ const totalHeight = shapeHeight * cellSize;
243
+ const offsetX = (size - totalWidth) / 2 - minCol * cellSize;
244
+ const offsetY = (size - totalHeight) / 2 - minRow * cellSize;
245
+ if (colors.length < 2) {
246
+ let svg2 = `<rect width="${size}" height="${size}" fill="${colors[0] || "#000000"}"/>`;
247
+ const fgColor2 = lightenColor(colors[0] || "#000000", 0.5);
248
+ for (let row = 0; row < gridSize; row++) {
249
+ for (let col = 0; col < gridSize; col++) {
250
+ if (fullGrid[row][col]) {
251
+ const x = offsetX + col * cellSize;
252
+ const y = offsetY + row * cellSize;
253
+ svg2 += `<rect x="${x}" y="${y}" width="${cellSize}" height="${cellSize}" fill="${fgColor2}"/>`;
254
+ }
255
+ }
256
+ }
257
+ return svg2;
258
+ }
259
+ const bgIndex = rng.randomInt(0, colors.length - 1);
260
+ let bgColor = colors[bgIndex];
261
+ const remainingColors = colors.filter((_, i) => i !== bgIndex);
262
+ let fgColor = rng.randomElement(remainingColors);
263
+ const bgLuminance = getLuminance(bgColor);
264
+ const fgLuminance = getLuminance(fgColor);
265
+ const luminanceDiff = Math.abs(bgLuminance - fgLuminance);
266
+ if (luminanceDiff < 0.15) {
267
+ if (bgLuminance < fgLuminance) {
268
+ bgColor = darkenColor(bgColor, 0.4);
269
+ } else {
270
+ bgColor = darkenColor(bgColor, 0.4);
271
+ }
272
+ if (fgLuminance > bgLuminance) {
273
+ fgColor = lightenColor(fgColor, 0.3);
274
+ } else {
275
+ fgColor = lightenColor(fgColor, 0.3);
276
+ }
277
+ }
278
+ let svg = `<rect width="${size}" height="${size}" fill="${bgColor}"/>`;
279
+ for (let row = 0; row < gridSize; row++) {
280
+ for (let col = 0; col < gridSize; col++) {
281
+ if (fullGrid[row][col]) {
282
+ const x = offsetX + col * cellSize;
283
+ const y = offsetY + row * cellSize;
284
+ svg += `<rect x="${x}" y="${y}" width="${cellSize}" height="${cellSize}" fill="${fgColor}"/>`;
285
+ }
286
+ }
287
+ }
288
+ return svg;
289
+ };
290
+
291
+ // src/pixelated.ts
292
+ var pixelated = (rng, options) => {
293
+ const size = options.size || 500;
294
+ const colors = options.colors || [];
295
+ let finalColors = [...colors];
296
+ const p = options.styleOptions || DEFAULT_PARAMETERS.pixelated;
297
+ if (p && p.colorsPerIcon) {
298
+ const shuffled = rng.shuffle([...colors]);
299
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
300
+ } else if (p && p.colorCount) {
301
+ const shuffled = rng.shuffle([...colors]);
302
+ finalColors = shuffled.slice(0, p.colorCount);
303
+ }
304
+ const config = { styleParameters: { pixelated: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
305
+ const params = { ...DEFAULT_PARAMETERS.pixelated, ...options.styleOptions || {} };
306
+ const blockSize = params.blockSize;
307
+ const patternType = params.patternType;
308
+ const colorVariation = params.colorVariation;
309
+ const gridSize = Math.floor(size / blockSize);
310
+ const baseColor = rng.randomElement(colors);
311
+ const accentColors = colors.filter((c) => c !== baseColor);
312
+ let svg = `<rect width="${size}" height="${size}" fill="${baseColor}"/>`;
313
+ for (let row = 0; row < gridSize; row++) {
314
+ for (let col = 0; col < Math.ceil(gridSize / 2); col++) {
315
+ let shouldFill = false;
316
+ switch (patternType) {
317
+ case "random":
318
+ shouldFill = rng.random() > 0.4;
319
+ break;
320
+ case "diagonal":
321
+ shouldFill = (row + col) % 3 !== 0 && rng.random() > 0.3;
322
+ break;
323
+ case "concentric":
324
+ const centerDist = Math.abs(row - gridSize / 2) + Math.abs(col - gridSize / 4);
325
+ shouldFill = Math.floor(centerDist) % 2 === 0 && rng.random() > 0.2;
326
+ break;
327
+ case "scattered":
328
+ shouldFill = rng.random() > 0.6;
329
+ break;
330
+ case "clustered":
331
+ const clusterHash = (Math.floor(col / 3) * 31 + Math.floor(row / 3) * 17) % 5;
332
+ shouldFill = clusterHash < 3 && rng.random() > 0.3;
333
+ break;
334
+ }
335
+ if (shouldFill) {
336
+ const fillColor = rng.random() < colorVariation ? rng.randomElement(accentColors.length > 0 ? accentColors : colors) : accentColors[0] || colors[1] || colors[0];
337
+ const x = Math.floor(col * blockSize);
338
+ const y = Math.floor(row * blockSize);
339
+ svg += `<rect x="${x}" y="${y}" width="${Math.ceil(blockSize)}" height="${Math.ceil(blockSize)}" fill="${fillColor}"/>`;
340
+ const mirrorCol = gridSize - 1 - col;
341
+ if (mirrorCol !== col) {
342
+ svg += `<rect x="${Math.floor(mirrorCol * blockSize)}" y="${y}" width="${Math.ceil(blockSize)}" height="${Math.ceil(blockSize)}" fill="${fillColor}"/>`;
343
+ }
344
+ }
345
+ }
346
+ }
347
+ return svg;
348
+ };
349
+
350
+ // src/mondrian.ts
351
+ var mondrian = (rng, options) => {
352
+ const size = options.size || 500;
353
+ const colors = options.colors || [];
354
+ let finalColors = [...colors];
355
+ const p = options.styleOptions || DEFAULT_PARAMETERS.mondrian;
356
+ if (p && p.colorsPerIcon) {
357
+ const shuffled = rng.shuffle([...colors]);
358
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
359
+ } else if (p && p.colorCount) {
360
+ const shuffled = rng.shuffle([...colors]);
361
+ finalColors = shuffled.slice(0, p.colorCount);
362
+ }
363
+ const config = { styleParameters: { mondrian: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
364
+ const params = { ...DEFAULT_PARAMETERS.mondrian, ...options.styleOptions || {} };
365
+ const divisionCount = params.divisionCount;
366
+ const lineThickness = params.lineThickness;
367
+ const balance = params.balance;
368
+ const sortedColors = [...colors].sort((a, b) => getLuminance(a) - getLuminance(b));
369
+ let svg = `<rect width="${size}" height="${size}" fill="${sortedColors[0]}"/>`;
370
+ const rectangles = [];
371
+ function subdivide(x, y, w, h, depth2) {
372
+ if (depth2 <= 0 || w < size * 0.1 && h < size * 0.1) {
373
+ rectangles.push({ x, y, w, h, color: rng.randomElement(colors) });
374
+ return;
375
+ }
376
+ const splitHorizontal = rng.random() > 0.5;
377
+ const minSize = size * (0.1 + balance * 0.1);
378
+ if (splitHorizontal && h > minSize) {
379
+ const splitRatio = balance < 0.5 ? 0.4 + rng.random() * 0.2 : 0.2 + rng.random() * 0.6;
380
+ const splitY = y + h * splitRatio;
381
+ subdivide(x, y, w, splitY - y - lineThickness, depth2 - 1);
382
+ subdivide(x, splitY + lineThickness, w, y + h - splitY - lineThickness, depth2 - 1);
383
+ } else if (!splitHorizontal && w > minSize) {
384
+ const splitRatio = balance < 0.5 ? 0.4 + rng.random() * 0.2 : 0.2 + rng.random() * 0.6;
385
+ const splitX = x + w * splitRatio;
386
+ subdivide(x, y, splitX - x - lineThickness, h, depth2 - 1);
387
+ subdivide(splitX + lineThickness, y, x + w - splitX - lineThickness, h, depth2 - 1);
388
+ } else {
389
+ rectangles.push({ x, y, w, h, color: rng.randomElement(colors) });
390
+ }
391
+ }
392
+ const depth = Math.ceil(divisionCount / 4);
393
+ subdivide(0, 0, size / 2, size, depth);
394
+ rectangles.forEach((rect) => {
395
+ svg += `<rect x="${rect.x}" y="${rect.y}" width="${rect.w}" height="${rect.h}" fill="${rect.color}"/>`;
396
+ svg += `<rect x="${size - rect.x - rect.w}" y="${rect.y}" width="${rect.w}" height="${rect.h}" fill="${rect.color}"/>`;
397
+ });
398
+ return svg;
399
+ };
400
+
401
+ // src/gradient.ts
402
+ var gradient = (rng, options) => {
403
+ const size = options.size || 500;
404
+ const colors = options.colors || [];
405
+ let finalColors = [...colors];
406
+ const p = options.styleOptions || DEFAULT_PARAMETERS.gradient;
407
+ if (p && p.colorsPerIcon) {
408
+ const shuffled = rng.shuffle([...colors]);
409
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
410
+ } else if (p && p.colorCount) {
411
+ const shuffled = rng.shuffle([...colors]);
412
+ finalColors = shuffled.slice(0, p.colorCount);
413
+ }
414
+ const config = { styleParameters: { gradient: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
415
+ const params = { ...DEFAULT_PARAMETERS.gradient, ...options.styleOptions || {} };
416
+ const maxComplexity = params.waveComplexity;
417
+ let direction = params.direction;
418
+ const blendSmoothness = params.blendSmoothness;
419
+ if (direction === "randomize") {
420
+ direction = rng.randomElement(["horizontal", "vertical", "diagonal", "radial"]);
421
+ }
422
+ const numPoints = Math.min(colors.length, 2 + rng.randomInt(1, maxComplexity + 1));
423
+ const startOffset = rng.random() * 0.2;
424
+ const endOffset = 1 - rng.random() * 0.2;
425
+ let gradDef = "";
426
+ const gradId = "grad";
427
+ if (direction === "radial") {
428
+ const offsetX = (rng.random() - 0.5) * 0.3;
429
+ const offsetY = (rng.random() - 0.5) * 0.3;
430
+ const cx = 50 + offsetX * 100;
431
+ const cy = 50 + offsetY * 100;
432
+ gradDef = `<radialGradient id="${gradId}" cx="${cx}%" cy="${cy}%">`;
433
+ } else {
434
+ let x1 = "0%", y1 = "50%", x2 = "100%", y2 = "50%";
435
+ if (direction === "horizontal") {
436
+ x1 = `${startOffset * 100}%`;
437
+ y1 = "50%";
438
+ x2 = `${endOffset * 100}%`;
439
+ y2 = "50%";
440
+ } else if (direction === "vertical") {
441
+ x1 = "50%";
442
+ y1 = `${startOffset * 100}%`;
443
+ x2 = "50%";
444
+ y2 = `${endOffset * 100}%`;
445
+ } else if (direction === "diagonal") {
446
+ const angle = rng.random() * Math.PI * 2;
447
+ const cos = Math.cos(angle);
448
+ const sin = Math.sin(angle);
449
+ x1 = `${50 + cos * 50}%`;
450
+ y1 = `${50 + sin * 50}%`;
451
+ x2 = `${50 - cos * 50}%`;
452
+ y2 = `${50 - sin * 50}%`;
453
+ }
454
+ gradDef = `<linearGradient id="${gradId}" x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}">`;
455
+ }
456
+ const shuffledColors = rng.shuffle([...colors]);
457
+ for (let i = 0; i < numPoints; i++) {
458
+ const position = i / (numPoints - 1);
459
+ const adjustedPosition = blendSmoothness > 0.5 ? position : Math.pow(position, 1 + (1 - blendSmoothness));
460
+ gradDef += `<stop offset="${(adjustedPosition * 100).toFixed(1)}%" stop-color="${shuffledColors[i % shuffledColors.length]}"/>`;
461
+ }
462
+ gradDef += direction === "radial" ? "</radialGradient>" : "</linearGradient>";
463
+ let svg = `<defs>${gradDef}</defs>`;
464
+ svg += `<rect width="${size}" height="${size}" fill="url(#${gradId})"/>`;
465
+ return svg;
466
+ };
467
+
468
+ // src/mosaic.ts
469
+ var mosaic = (rng, options) => {
470
+ const size = options.size || 500;
471
+ const colors = options.colors || [];
472
+ let finalColors = [...colors];
473
+ const p = options.styleOptions || DEFAULT_PARAMETERS.mosaic;
474
+ if (p && p.colorsPerIcon) {
475
+ const shuffled = rng.shuffle([...colors]);
476
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
477
+ } else if (p && p.colorCount) {
478
+ const shuffled = rng.shuffle([...colors]);
479
+ finalColors = shuffled.slice(0, p.colorCount);
480
+ }
481
+ const config = { styleParameters: { mosaic: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
482
+ const params = { ...DEFAULT_PARAMETERS.mosaic, ...options.styleOptions || {} };
483
+ const tileCount = params.tileCount;
484
+ const tileSizeVariation = params.tileSizeVariation;
485
+ const gapSize = params.gapSize;
486
+ const seedPoints = [];
487
+ const minDistance = size / Math.sqrt(tileCount) * (1 - tileSizeVariation * 0.8);
488
+ let attempts = 0;
489
+ while (seedPoints.length < tileCount && attempts < tileCount * 50) {
490
+ attempts++;
491
+ const x = rng.random() * size;
492
+ const y = rng.random() * size;
493
+ let tooClose = false;
494
+ for (const existing of seedPoints) {
495
+ const dx = x - existing.x;
496
+ const dy = y - existing.y;
497
+ const dist = Math.sqrt(dx * dx + dy * dy);
498
+ if (dist < minDistance * (1 - tileSizeVariation * rng.random())) {
499
+ tooClose = true;
500
+ break;
501
+ }
502
+ }
503
+ if (!tooClose) {
504
+ seedPoints.push({ x, y, color: rng.randomElement(colors) });
505
+ }
506
+ }
507
+ if (seedPoints.length === 0) {
508
+ return `<rect width="${size}" height="${size}" fill="${colors[0] || "#000"}"/>`;
509
+ }
510
+ let svg = `<rect width="${size}" height="${size}" fill="${colors[0]}"/>`;
511
+ function clipPolygon(poly, p1, p2) {
512
+ const mx = (p1.x + p2.x) / 2;
513
+ const my = (p1.y + p2.y) / 2;
514
+ const nx = p2.x - p1.x;
515
+ const ny = p2.y - p1.y;
516
+ const isInside = (p3) => (p3.x - mx) * nx + (p3.y - my) * ny <= 1e-5;
517
+ const getIntersect = (A, B) => {
518
+ const num = (mx - A.x) * nx + (my - A.y) * ny;
519
+ const den = (B.x - A.x) * nx + (B.y - A.y) * ny;
520
+ const t = num / den;
521
+ return { x: A.x + t * (B.x - A.x), y: A.y + t * (B.y - A.y) };
522
+ };
523
+ const out = [];
524
+ for (let i = 0; i < poly.length; i++) {
525
+ const cur = poly[i];
526
+ const prev = poly[(i - 1 + poly.length) % poly.length];
527
+ const curIn = isInside(cur);
528
+ const prevIn = isInside(prev);
529
+ if (curIn !== prevIn) {
530
+ out.push(getIntersect(prev, cur));
531
+ }
532
+ if (curIn) {
533
+ out.push(cur);
534
+ }
535
+ }
536
+ return out;
537
+ }
538
+ for (let i = 0; i < seedPoints.length; i++) {
539
+ const sp = seedPoints[i];
540
+ let poly = [
541
+ { x: -10, y: -10 },
542
+ { x: size + 10, y: -10 },
543
+ { x: size + 10, y: size + 10 },
544
+ { x: -10, y: size + 10 }
545
+ ];
546
+ for (let j = 0; j < seedPoints.length; j++) {
547
+ if (i === j) continue;
548
+ poly = clipPolygon(poly, sp, seedPoints[j]);
549
+ if (poly.length < 3) break;
550
+ }
551
+ if (poly.length >= 3) {
552
+ const pointsStr = poly.map((p2) => `${p2.x.toFixed(2)},${p2.y.toFixed(2)}`).join(" ");
553
+ svg += `<polygon points="${pointsStr}" fill="${sp.color}"`;
554
+ if (gapSize > 0) {
555
+ svg += ` stroke="rgba(0,0,0,0.3)" stroke-width="${gapSize * 2}" stroke-linejoin="miter"`;
556
+ } else {
557
+ svg += ` stroke="${sp.color}" stroke-width="0.5"`;
558
+ }
559
+ svg += `/>`;
560
+ }
561
+ }
562
+ return svg;
563
+ };
564
+
565
+ // src/waves.ts
566
+ var waves = (rng, options) => {
567
+ const size = options.size || 500;
568
+ const colors = options.colors || [];
569
+ let finalColors = [...colors];
570
+ const p = options.styleOptions || DEFAULT_PARAMETERS.waves;
571
+ if (p && p.colorsPerIcon) {
572
+ const shuffled = rng.shuffle([...colors]);
573
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
574
+ } else if (p && p.colorCount) {
575
+ const shuffled = rng.shuffle([...colors]);
576
+ finalColors = shuffled.slice(0, p.colorCount);
577
+ }
578
+ const config = { styleParameters: { waves: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
579
+ const params = { ...DEFAULT_PARAMETERS.waves, ...options.styleOptions || {} };
580
+ const maxWaveCount = params.waveCount;
581
+ const maxAmplitude = params.amplitude * size;
582
+ const maxFrequency = params.frequency;
583
+ let direction = params.direction;
584
+ if (direction === "randomize") {
585
+ direction = rng.randomElement(["horizontal", "vertical", "diagonal", "radial"]);
586
+ }
587
+ const waveCount = rng.randomInt(Math.max(1, Math.floor(maxWaveCount * 0.5)), maxWaveCount + 1);
588
+ const amplitude = maxAmplitude * (0.5 + rng.random() * 0.5);
589
+ const frequency = rng.random() * maxFrequency;
590
+ if (direction === "radial") {
591
+ const centerX = size / 2 + (rng.random() - 0.5) * size * 0.2;
592
+ const centerY = size / 2 + (rng.random() - 0.5) * size * 0.2;
593
+ const maxRadius = size / Math.sqrt(2);
594
+ const shuffledColors2 = rng.shuffle([...colors]);
595
+ let svg2 = "";
596
+ for (let i = waveCount; i >= 0; i--) {
597
+ const radius = i / waveCount * maxRadius;
598
+ svg2 += `<circle cx="${centerX}" cy="${centerY}" r="${radius}" fill="${shuffledColors2[i % shuffledColors2.length]}"/>`;
599
+ }
600
+ return svg2;
601
+ }
602
+ const spacing = size / (waveCount + 1);
603
+ const wavePoints = [];
604
+ for (let w = 0; w < waveCount; w++) {
605
+ const baseY = spacing * (w + 1);
606
+ const points = [];
607
+ const phase = rng.random() * Math.PI * 2;
608
+ for (let i = 0; i <= 100; i++) {
609
+ const x = i / 100 * size;
610
+ const y = baseY + Math.sin(i / 100 * Math.PI * 2 * frequency + phase) * amplitude;
611
+ points.push({ x, y });
612
+ }
613
+ wavePoints.push(points);
614
+ }
615
+ const shuffledColors = rng.shuffle([...colors]);
616
+ function pointsToPath(pts) {
617
+ let d = `M ${pts[0].x} ${pts[0].y}`;
618
+ for (let i = 1; i < pts.length; i++) {
619
+ d += ` L ${pts[i].x} ${pts[i].y}`;
620
+ }
621
+ return d;
622
+ }
623
+ function pointsToReversePath(pts) {
624
+ let d = "";
625
+ for (let i = pts.length - 1; i >= 0; i--) {
626
+ d += ` L ${pts[i].x} ${pts[i].y}`;
627
+ }
628
+ return d;
629
+ }
630
+ let svg = "";
631
+ let transformStart = "";
632
+ let transformEnd = "";
633
+ if (direction === "vertical") {
634
+ transformStart = `<g transform="translate(${size},0) rotate(90)">`;
635
+ transformEnd = `</g>`;
636
+ } else if (direction === "diagonal") {
637
+ transformStart = `<g transform="translate(${size / 2},${size / 2}) rotate(45) translate(-${size / 2},-${size / 2})">`;
638
+ transformEnd = `</g>`;
639
+ }
640
+ svg += transformStart;
641
+ const firstWavePath = pointsToPath(wavePoints[0]);
642
+ svg += `<path d="${firstWavePath} L ${size} 0 L 0 0 Z" fill="${shuffledColors[0]}"/>`;
643
+ for (let w = 0; w < waveCount - 1; w++) {
644
+ const topPath = pointsToPath(wavePoints[w]);
645
+ const bottomReversed = pointsToReversePath(wavePoints[w + 1]);
646
+ svg += `<path d="${topPath}${bottomReversed} Z" fill="${shuffledColors[(w + 1) % shuffledColors.length]}"/>`;
647
+ }
648
+ const lastWavePath = pointsToPath(wavePoints[waveCount - 1]);
649
+ svg += `<path d="${lastWavePath} L ${size} ${size} L 0 ${size} Z" fill="${shuffledColors[waveCount % shuffledColors.length]}"/>`;
650
+ svg += transformEnd;
651
+ return svg;
652
+ };
653
+
654
+ // src/polycon.ts
655
+ var polycon = (rng, options) => {
656
+ const size = options.size || 500;
657
+ const colors = options.colors || [];
658
+ let finalColors = [...colors];
659
+ const p = options.styleOptions || DEFAULT_PARAMETERS.polycon;
660
+ if (p && p.colorsPerIcon) {
661
+ const shuffled = rng.shuffle([...colors]);
662
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
663
+ } else if (p && p.colorCount) {
664
+ const shuffled = rng.shuffle([...colors]);
665
+ finalColors = shuffled.slice(0, p.colorCount);
666
+ }
667
+ const config = { styleParameters: { polycon: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
668
+ const params = { ...DEFAULT_PARAMETERS.polycon, ...options.styleOptions || {} };
669
+ const gridSize = params.gridSize;
670
+ const emptyProb = params.emptyProbability;
671
+ const fullSquareProb = params.fullSquareProbability;
672
+ const shuffledAllColors = rng.shuffle([...colors]);
673
+ const selectedColors = shuffledAllColors.slice(0, params.colorsPerIcon);
674
+ const outerColor = selectedColors[0];
675
+ let svg = `<rect width="${size}" height="${size}" fill="${outerColor}"/>`;
676
+ const innerSquareSizeRaw = size * 0.65;
677
+ const cellSize = Math.floor(innerSquareSizeRaw / gridSize);
678
+ const innerSquareSize = cellSize * gridSize;
679
+ const innerSquareX = Math.floor((size - innerSquareSize) / 2);
680
+ const innerSquareY = Math.floor((size - innerSquareSize) / 2);
681
+ const sortedByLuminance = [...selectedColors].sort((a, b) => getLuminance(a) - getLuminance(b));
682
+ const darkColor = sortedByLuminance[0];
683
+ svg += `<rect x="${innerSquareX}" y="${innerSquareY}" width="${innerSquareSize}" height="${innerSquareSize}" fill="${darkColor}" stroke="none" stroke-width="0"/>`;
684
+ const brightColors = sortedByLuminance.slice(1);
685
+ if (brightColors.length === 0) brightColors.push(sortedByLuminance[0]);
686
+ const triangleProb = 1 - emptyProb - fullSquareProb;
687
+ for (let row = 0; row < gridSize; row++) {
688
+ for (let col = 0; col < gridSize; col++) {
689
+ const x = innerSquareX + col * cellSize;
690
+ const y = innerSquareY + row * cellSize;
691
+ const rand = rng.random();
692
+ if (rand < emptyProb) {
693
+ continue;
694
+ } else if (rand < emptyProb + fullSquareProb) {
695
+ const color = rng.randomElement(brightColors);
696
+ svg += `<rect x="${x}" y="${y}" width="${cellSize}" height="${cellSize}" fill="${color}" stroke="none" stroke-width="0"/>`;
697
+ } else {
698
+ const triangleRand = rng.random();
699
+ let triangleType;
700
+ if (triangleRand < 0.25) {
701
+ triangleType = 0;
702
+ } else if (triangleRand < 0.5) {
703
+ triangleType = 1;
704
+ } else if (triangleRand < 0.75) {
705
+ triangleType = 2;
706
+ } else {
707
+ triangleType = 3;
708
+ }
709
+ let points = "";
710
+ switch (triangleType) {
711
+ case 0:
712
+ points = `${x},${y} ${x + cellSize},${y} ${x},${y + cellSize}`;
713
+ break;
714
+ case 1:
715
+ points = `${x},${y} ${x + cellSize},${y} ${x + cellSize},${y + cellSize}`;
716
+ break;
717
+ case 2:
718
+ points = `${x + cellSize},${y} ${x + cellSize},${y + cellSize} ${x},${y + cellSize}`;
719
+ break;
720
+ case 3:
721
+ points = `${x},${y} ${x},${y + cellSize} ${x + cellSize},${y + cellSize}`;
722
+ break;
723
+ }
724
+ const color = rng.randomElement(brightColors);
725
+ svg += `<polygon points="${points}" fill="${color}" stroke="none" stroke-width="0"/>`;
726
+ }
727
+ }
728
+ }
729
+ return svg;
730
+ };
731
+
732
+ // src/inkblot.ts
733
+ var inkblot = (rng, options) => {
734
+ const size = options.size || 500;
735
+ const colors = options.colors || [];
736
+ let finalColors = [...colors];
737
+ const p = options.styleOptions || DEFAULT_PARAMETERS.inkblot;
738
+ if (p && p.colorsPerIcon) {
739
+ const shuffled = rng.shuffle([...colors]);
740
+ finalColors = shuffled.slice(0, p.colorsPerIcon);
741
+ } else if (p && p.colorCount) {
742
+ const shuffled = rng.shuffle([...colors]);
743
+ finalColors = shuffled.slice(0, p.colorCount);
744
+ }
745
+ const config = { styleParameters: { inkblot: p }, isCircle: options.isCircle, borderRadius: options.borderRadius };
746
+ const params = { ...DEFAULT_PARAMETERS.inkblot, ...options.styleOptions || {} };
747
+ const blobCount = params.blobCount;
748
+ const spread = params.spread;
749
+ const symmetry = params.symmetry;
750
+ const centered = params.centered;
751
+ const bgColor = rng.randomElement(colors);
752
+ let inkColor = rng.randomElement(colors);
753
+ if (bgColor === inkColor && colors.length > 1) {
754
+ inkColor = colors[(colors.indexOf(inkColor) + 1) % colors.length];
755
+ }
756
+ let svg = `<rect width="${size}" height="${size}" fill="${bgColor}"/>`;
757
+ const halfWidth = symmetry === "vertical" || symmetry === "both" ? Math.ceil(size / 2) : size;
758
+ const halfHeight = symmetry === "horizontal" || symmetry === "both" ? Math.ceil(size / 2) : size;
759
+ function drawBlob(centerX, centerY, radius) {
760
+ const numPoints = rng.randomInt(8, 13);
761
+ const points = [];
762
+ for (let i = 0; i < numPoints; i++) {
763
+ const angle = i / numPoints * Math.PI * 2;
764
+ const distance = radius * (0.6 + rng.random() * 0.8);
765
+ points.push({
766
+ x: centerX + Math.cos(angle) * distance,
767
+ y: centerY + Math.sin(angle) * distance
768
+ });
769
+ }
770
+ let path = `M ${points[0].x} ${points[0].y}`;
771
+ for (let i = 0; i < numPoints; i++) {
772
+ const current = points[i];
773
+ const next = points[(i + 1) % numPoints];
774
+ const controlX = (current.x + next.x) / 2;
775
+ const controlY = (current.y + next.y) / 2;
776
+ path += ` Q ${current.x} ${current.y} ${controlX} ${controlY}`;
777
+ }
778
+ path += " Z";
779
+ return path;
780
+ }
781
+ let blobs = "";
782
+ for (let i = 0; i < blobCount; i++) {
783
+ const spreadRange = spread * (centered ? 0.3 : 0.7);
784
+ const centerX = halfWidth * (0.5 - spreadRange + rng.random() * spreadRange * 2);
785
+ const centerY = halfHeight * (0.5 - spreadRange + rng.random() * spreadRange * 2);
786
+ const radius = size * (0.05 + rng.random() * 0.15);
787
+ blobs += `<path d="${drawBlob(centerX, centerY, radius)}" fill="${inkColor}"/>`;
788
+ }
789
+ if (symmetry === "none") {
790
+ svg += blobs;
791
+ } else if (symmetry === "vertical") {
792
+ svg += blobs;
793
+ svg += `<g transform="scale(-1,1) translate(-${size},0)">${blobs}</g>`;
794
+ } else if (symmetry === "horizontal") {
795
+ svg += blobs;
796
+ svg += `<g transform="scale(1,-1) translate(0,-${size})">${blobs}</g>`;
797
+ } else if (symmetry === "both") {
798
+ svg += blobs;
799
+ svg += `<g transform="scale(-1,1) translate(-${size},0)">${blobs}</g>`;
800
+ svg += `<g transform="scale(1,-1) translate(0,-${size})">${blobs}</g>`;
801
+ svg += `<g transform="scale(-1,-1) translate(-${size},-${size})">${blobs}</g>`;
802
+ }
803
+ return svg;
804
+ };
805
+
806
+ // src/palettes.ts
807
+ var palettes = {
808
+ sunset: ["#FF6B6B", "#FF8E53", "#FFC857", "#E85D75", "#4A1942"],
809
+ ocean: ["#0077B6", "#00B4D8", "#90E0EF", "#023E8A", "#CAF0F8"],
810
+ forest: ["#2D6A4F", "#40916C", "#74C69D", "#1B4332", "#D8F3DC"],
811
+ neon: ["#FF006E", "#8338EC", "#3A86FF", "#FFBE0B", "#FB5607"],
812
+ pastel: ["#FFB5A7", "#FCD5CE", "#F8EDEB", "#F9DCC4", "#FEC89A"],
813
+ earth: ["#BC6C25", "#DDA15E", "#606C38", "#283618", "#FEFAE0"],
814
+ mono: ["#F8F9FA", "#DEE2E6", "#ADB5BD", "#495057", "#212529"],
815
+ candy: ["#F72585", "#7209B7", "#3A0CA3", "#4361EE", "#4CC9F0"]
816
+ };
817
+ var paletteNames = Object.keys(palettes);
818
+ var DEFAULT_PALETTE = "neon";
819
+ var DEFAULT_COLORS = palettes[DEFAULT_PALETTE];
820
+ // Annotate the CommonJS export names for ESM import in node:
821
+ 0 && (module.exports = {
822
+ DEFAULT_COLORS,
823
+ DEFAULT_PALETTE,
824
+ DEFAULT_PARAMETERS,
825
+ gradient,
826
+ inkblot,
827
+ mondrian,
828
+ mosaic,
829
+ paletteNames,
830
+ palettes,
831
+ pixel,
832
+ pixelated,
833
+ polycon,
834
+ waves
835
+ });