boring-avatars-vanilla 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hustcc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # boring-avatars-vanilla
2
+
3
+ Boring avatars is a tiny JavaScript library that generates custom, SVG-based avatars from any username and color palette. Works in both browsers and Node.js server-side rendering.
4
+
5
+ ![boring-avatars-preview](./boring-avatars-preview.png)
6
+
7
+ <a href="https://www.npmjs.com/package/boring-avatars-vanilla">
8
+
9
+ ![npm](https://badgen.net/npm/v/boring-avatars-vanilla)
10
+ ![build](https://github.com/boringdesigners/boring-avatars/actions/workflows/build.yml/badge.svg)
11
+ ![deploy](https://github.com/boringdesigners/boring-avatars/actions/workflows/deploy.yml/badge.svg)
12
+
13
+ </a>
14
+
15
+ ## Install
16
+
17
+ ```
18
+ npm install boring-avatars-vanilla
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```javascript
24
+ import boring from 'boring-avatars-vanilla';
25
+
26
+ const svg = boring({ name: 'Maria Mitchell' });
27
+
28
+ // Use in browser
29
+ document.getElementById('avatar').innerHTML = svg;
30
+
31
+ // Use in Node.js server-side rendering
32
+ fs.writeFileSync('avatar.svg', svg);
33
+ ```
34
+
35
+ ### Props
36
+
37
+ | Prop | Type | Default |
38
+ |---------|--------------------------------------------------------------|-----------------------------------------------------------|
39
+ | size | number or string | `40px` |
40
+ | square | boolean | `false` |
41
+ | title | boolean | `false` |
42
+ | name | string | `Clara Barton` |
43
+ | variant | oneOf: `marble`, `beam`, `pixel`,`sunset`, `ring`, `bauhaus` | `marble` |
44
+ | colors | array | `['#92A1C6', '#146A7C', '#F0AB3D', '#C271B4', '#C20D90']` |
45
+
46
+
47
+ #### Name
48
+
49
+ The `name` prop is used to generate the avatar. It can be the username, email or any random string.
50
+
51
+ ```javascript
52
+ boring({ name: 'Maria Mitchell' });
53
+ ```
54
+
55
+ #### Variant
56
+
57
+ The `variant` prop is used to change the theme of the avatar. The available variants are: `marble`, `beam`, `pixel`, `sunset`, `ring` and `bauhaus`.
58
+
59
+ ```javascript
60
+ boring({ name: 'Alice Paul', variant: 'beam' });
61
+ ```
62
+
63
+ #### Size
64
+
65
+ The `size` prop is used to change the size of the avatar.
66
+
67
+ ```javascript
68
+ boring({ name: 'Ada Lovelace', size: 88 });
69
+ ```
70
+
71
+ #### Colors
72
+
73
+ The `colors` prop is used to change the color palette of the avatar.
74
+
75
+ ```javascript
76
+ boring({ name: 'Grace Hopper', colors: ['#fb6900', '#f63700', '#004853', '#007e80', '#00b9bd'] });
77
+ ```
78
+
79
+ #### Square
80
+
81
+ The `square` prop is used to make the avatar square.
82
+
83
+ ```javascript
84
+ boring({ name: 'Helen Keller', square: true });
85
+ ```
86
+
87
+ ## API service
88
+
89
+ > [!IMPORTANT]
90
+ > Please note that the old service was paused in July 31st 2024. We recommend transitioning to our new API service to ensure uninterrupted access and support.
91
+
92
+ Get access to the Boring avatars API service [here →](https://boringdesigners.gumroad.com/l/boring-avatars-service).
93
+
94
+ ## License
95
+
96
+ MIT, Thanks for [boring-avatars](https://github.com/boringdesigners/boring-avatars).
package/dist/index.cjs ADDED
@@ -0,0 +1,169 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const S=s=>{let e=0;for(let r=0;r<s.length;r++){const a=s.charCodeAt(r);e=(e<<5)-e+a,e=e&e}return Math.abs(e)},M=(s,e)=>Math.floor(s/Math.pow(10,e)%10),y=(s,e)=>!(M(s,e)%2),p=(s,e,r)=>{const a=s%e;return r&&M(s,r)%2===0?-a:a},w=(s,e,r)=>e[s%r],_=s=>{s.slice(0,1)==="#"&&(s=s.slice(1));const e=parseInt(s.substr(0,2),16),r=parseInt(s.substr(2,2),16),a=parseInt(s.substr(4,2),16);return(e*299+r*587+a*114)/1e3>=128?"#000000":"#FFFFFF"};let U=0;const k=()=>`boring-avatar-${++U}-${Date.now().toString(36)}`,B=3,h=80;function L(s,e){const r=S(s),a=e.length;return Array.from({length:B},(n,t)=>({color:w(r+t,e,a),translateX:p(r*(t+1),h/10,1),translateY:p(r*(t+1),h/10,2),scale:1.2+p(r*(t+1),h/20)/10,rotate:p(r*(t+1),360,1)}))}const z=s=>{const{name:e,colors:r,title:a,square:o,size:n="40px"}=s,t=L(e,r),i=k(),c=typeof n=="number"?`${n}px`:n,f=o?`<rect width="${h}" height="${h}" fill="#FFFFFF" />`:`<rect width="${h}" height="${h}" rx="${h*2}" fill="#FFFFFF" />`;return`<svg
2
+ viewBox="0 0 ${h} ${h}"
3
+ fill="none"
4
+ role="img"
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ width="${c}"
7
+ height="${c}"
8
+ >
9
+ ${a?`<title>${e}</title>`:""}
10
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${h}" height="${h}">
11
+ ${f}
12
+ </mask>
13
+ <g mask="url(#${i})">
14
+ <rect width="${h}" height="${h}" fill="${t[0].color}" />
15
+ <path
16
+ filter="url(#filter_${i})"
17
+ d="M32.414 59.35L50.376 70.5H72.5v-71H33.728L26.5 13.381l19.057 27.08L32.414 59.35z"
18
+ fill="${t[1].color}"
19
+ transform="translate(${t[1].translateX} ${t[1].translateY}) rotate(${t[1].rotate} ${h/2} ${h/2}) scale(${t[2].scale})"
20
+ />
21
+ <path
22
+ filter="url(#filter_${i})"
23
+ style="mix-blend-mode: overlay"
24
+ d="M22.216 24L0 46.75l14.108 38.129L78 86l-3.081-59.276-22.378 4.005 12.972 20.186-23.35 27.395L22.215 24z"
25
+ fill="${t[2].color}"
26
+ transform="translate(${t[2].translateX} ${t[2].translateY}) rotate(${t[2].rotate} ${h/2} ${h/2}) scale(${t[2].scale})"
27
+ />
28
+ </g>
29
+ <defs>
30
+ <filter id="filter_${i}" filterUnits="userSpaceOnUse" colorInterpolationFilters="sRGB">
31
+ <feFlood floodOpacity="0" result="BackgroundImageFix" />
32
+ <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
33
+ <feGaussianBlur stdDeviation="7" result="effect1_foregroundBlur" />
34
+ </filter>
35
+ </defs>
36
+ </svg>`},O=64,m=80;function T(s,e){const r=S(s),a=e.length;return Array.from({length:O},(n,t)=>w(r%(t+1),e,a))}const D=s=>{const{name:e,colors:r,title:a,square:o,size:n="40px"}=s,t=T(e,r),i=k(),c=typeof n=="number"?`${n}px`:n,f=o?`<rect width="${m}" height="${m}" fill="#FFFFFF" />`:`<rect width="${m}" height="${m}" rx="${m*2}" fill="#FFFFFF" />`,u=[],F=[[0,0],[20,0],[40,0],[60,0],[10,0],[30,0],[50,0],[70,0],[0,10],[0,20],[0,30],[0,40],[0,50],[0,60],[0,70],[20,10],[20,20],[20,30],[20,40],[20,50],[20,60],[20,70],[40,10],[40,20],[40,30],[40,40],[40,50],[40,60],[40,70],[60,10],[60,20],[60,30],[60,40],[60,50],[60,60],[60,70],[10,10],[10,20],[10,30],[10,40],[10,50],[10,60],[10,70],[30,10],[30,20],[30,30],[30,40],[30,50],[30,60],[30,70],[50,10],[50,20],[50,30],[50,40],[50,50],[50,60],[50,70],[70,10],[70,20],[70,30],[70,40],[70,50],[70,60],[70,70]];for(let x=0;x<F.length;x++){const[I,E]=F[x];u.push(` <rect x="${I}" y="${E}" width="10" height="10" fill="${t[x]}" />`)}return`<svg
37
+ viewBox="0 0 ${m} ${m}"
38
+ fill="none"
39
+ role="img"
40
+ xmlns="http://www.w3.org/2000/svg"
41
+ width="${c}"
42
+ height="${c}"
43
+ >
44
+ ${a?`<title>${e}</title>`:""}
45
+ <mask id="${i}" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="${m}" height="${m}">
46
+ ${f}
47
+ </mask>
48
+ <g mask="url(#${i})">
49
+ ${u.join(`
50
+ `)}
51
+ </g>
52
+ </svg>`},d=90,A=5;function N(s,e){const r=S(s),a=e.length,o=Array.from({length:A},(t,i)=>w(r+i,e,a)),n=[];return n[0]=o[0],n[1]=o[1],n[2]=o[1],n[3]=o[2],n[4]=o[2],n[5]=o[3],n[6]=o[3],n[7]=o[0],n[8]=o[4],n}const R=s=>{const{name:e,colors:r,title:a,square:o,size:n="40px"}=s,t=N(e,r),i=k(),c=typeof n=="number"?`${n}px`:n,f=o?`<rect width="${d}" height="${d}" fill="#FFFFFF" />`:`<rect width="${d}" height="${d}" rx="${d*2}" fill="#FFFFFF" />`;return`<svg
53
+ viewBox="0 0 ${d} ${d}"
54
+ fill="none"
55
+ role="img"
56
+ xmlns="http://www.w3.org/2000/svg"
57
+ width="${c}"
58
+ height="${c}"
59
+ >
60
+ ${a?`<title>${e}</title>`:""}
61
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${d}" height="${d}">
62
+ ${f}
63
+ </mask>
64
+ <g mask="url(#${i})">
65
+ <path d="M0 0h90v45H0z" fill="${t[0]}" />
66
+ <path d="M0 45h90v45H0z" fill="${t[1]}" />
67
+ <path d="M83 45a38 38 0 00-76 0h76z" fill="${t[2]}" />
68
+ <path d="M83 45a38 38 0 01-76 0h76z" fill="${t[3]}" />
69
+ <path d="M77 45a32 32 0 10-64 0h64z" fill="${t[4]}" />
70
+ <path d="M77 45a32 32 0 11-64 0h64z" fill="${t[5]}" />
71
+ <path d="M71 45a26 26 0 00-52 0h52z" fill="${t[6]}" />
72
+ <path d="M71 45a26 26 0 01-52 0h52z" fill="${t[7]}" />
73
+ <circle cx="45" cy="45" r="23" fill="${t[8]}" />
74
+ </g>
75
+ </svg>`},$=36;function X(s,e){const r=S(s),a=e.length,o=w(r,e,a),n=p(r,10,1),t=n<5?n+$/9:n,i=p(r,10,2),c=i<5?i+$/9:i;return{wrapperColor:o,faceColor:_(o),backgroundColor:w(r+13,e,a),wrapperTranslateX:t,wrapperTranslateY:c,wrapperRotate:p(r,360),wrapperScale:1+p(r,$/12)/10,isMouthOpen:y(r,2),isCircle:y(r,1),eyeSpread:p(r,5),mouthSpread:p(r,3),faceRotate:p(r,10,3),faceTranslateX:t>$/6?t/2:p(r,8,1),faceTranslateY:c>$/6?c/2:p(r,7,2)}}const v=s=>{const{name:e,colors:r,title:a,square:o,size:n="40px"}=s,t=X(e,r),i=k(),c=typeof n=="number"?`${n}px`:n,f=o?`<rect width="${$}" height="${$}" fill="#FFFFFF" />`:`<rect width="${$}" height="${$}" rx="${$*2}" fill="#FFFFFF" />`,u=t.isMouthOpen?`<path d="M15 ${19+t.mouthSpread}c2 1 4 1 6 0" stroke="${t.faceColor}" fill="none" stroke-linecap="round" />`:`<path d="M13,${19+t.mouthSpread} a1,0.75 0 0,0 10,0" fill="${t.faceColor}" />`,F=t.isCircle?$:$/6;return`<svg
76
+ viewBox="0 0 ${$} ${$}"
77
+ fill="none"
78
+ role="img"
79
+ xmlns="http://www.w3.org/2000/svg"
80
+ width="${c}"
81
+ height="${c}"
82
+ >
83
+ ${a?`<title>${e}</title>`:""}
84
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${$}" height="${$}">
85
+ ${f}
86
+ </mask>
87
+ <g mask="url(#${i})">
88
+ <rect width="${$}" height="${$}" fill="${t.backgroundColor}" />
89
+ <rect
90
+ x="0"
91
+ y="0"
92
+ width="${$}"
93
+ height="${$}"
94
+ transform="translate(${t.wrapperTranslateX} ${t.wrapperTranslateY}) rotate(${t.wrapperRotate} ${$/2} ${$/2}) scale(${t.wrapperScale})"
95
+ fill="${t.wrapperColor}"
96
+ rx="${F}"
97
+ />
98
+ <g transform="translate(${t.faceTranslateX} ${t.faceTranslateY}) rotate(${t.faceRotate} ${$/2} ${$/2})">
99
+ ${u}
100
+ <rect x="${14-t.eyeSpread}" y="14" width="1.5" height="2" rx="1" stroke="none" fill="${t.faceColor}" />
101
+ <rect x="${20+t.eyeSpread}" y="14" width="1.5" height="2" rx="1" stroke="none" fill="${t.faceColor}" />
102
+ </g>
103
+ </g>
104
+ </svg>`},Y=4,l=80;function q(s,e){const r=S(s),a=e.length;return Array.from({length:Y},(n,t)=>({color:w(r+t,e,a),translateX:p(r*(t+1),l/2-(t+17),1),translateY:p(r*(t+1),l/2-(t+17),2),rotate:p(r*(t+1),360),isSquare:y(r,2)}))}const C=s=>{const{name:e,colors:r,title:a,square:o,size:n="40px"}=s,t=q(e,r),i=k(),c=typeof n=="number"?`${n}px`:n,f=o?`<rect width="${l}" height="${l}" fill="#FFFFFF" />`:`<rect width="${l}" height="${l}" rx="${l*2}" fill="#FFFFFF" />`,u=t[1].isSquare?l:l/8;return`<svg
105
+ viewBox="0 0 ${l} ${l}"
106
+ fill="none"
107
+ role="img"
108
+ xmlns="http://www.w3.org/2000/svg"
109
+ width="${c}"
110
+ height="${c}"
111
+ >
112
+ ${a?`<title>${e}</title>`:""}
113
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${l}" height="${l}">
114
+ ${f}
115
+ </mask>
116
+ <g mask="url(#${i})">
117
+ <rect width="${l}" height="${l}" fill="${t[0].color}" />
118
+ <rect
119
+ x="${(l-60)/2}"
120
+ y="${(l-20)/2}"
121
+ width="${l}"
122
+ height="${u}"
123
+ fill="${t[1].color}"
124
+ transform="translate(${t[1].translateX} ${t[1].translateY}) rotate(${t[1].rotate} ${l/2} ${l/2})"
125
+ />
126
+ <circle
127
+ cx="${l/2}"
128
+ cy="${l/2}"
129
+ fill="${t[2].color}"
130
+ r="${l/5}"
131
+ transform="translate(${t[2].translateX} ${t[2].translateY})"
132
+ />
133
+ <line
134
+ x1="0"
135
+ y1="${l/2}"
136
+ x2="${l}"
137
+ y2="${l/2}"
138
+ stroke-width="2"
139
+ stroke="${t[3].color}"
140
+ transform="translate(${t[3].translateX} ${t[3].translateY}) rotate(${t[3].rotate} ${l/2} ${l/2})"
141
+ />
142
+ </g>
143
+ </svg>`},G=4,g=80;function H(s,e){const r=S(s),a=e.length;return Array.from({length:G},(n,t)=>w(r+t,e,a))}const P=s=>{const{name:e,colors:r,title:a,square:o,size:n="40px"}=s,t=H(e,r),i=e.replace(/\s/g,""),c=k(),f=`gradient_paint0_linear_${i}_${c}`,u=`gradient_paint1_linear_${i}_${c}`,F=typeof n=="number"?`${n}px`:n,x=o?`<rect width="${g}" height="${g}" fill="#FFFFFF" />`:`<rect width="${g}" height="${g}" rx="${g*2}" fill="#FFFFFF" />`;return`<svg
144
+ viewBox="0 0 ${g} ${g}"
145
+ fill="none"
146
+ role="img"
147
+ xmlns="http://www.w3.org/2000/svg"
148
+ width="${F}"
149
+ height="${F}"
150
+ >
151
+ ${a?`<title>${e}</title>`:""}
152
+ <mask id="${c}" maskUnits="userSpaceOnUse" x="0" y="0" width="${g}" height="${g}">
153
+ ${x}
154
+ </mask>
155
+ <g mask="url(#${c})">
156
+ <path fill="url(#${f})" d="M0 0h80v40H0z" />
157
+ <path fill="url(#${u})" d="M0 40h80v40H0z" />
158
+ </g>
159
+ <defs>
160
+ <linearGradient id="${f}" x1="${g/2}" y1="0" x2="${g/2}" y2="${g/2}" gradientUnits="userSpaceOnUse">
161
+ <stop stop-color="${t[0]}" />
162
+ <stop offset="1" stop-color="${t[1]}" />
163
+ </linearGradient>
164
+ <linearGradient id="${u}" x1="${g/2}" y1="${g/2}" x2="${g/2}" y2="${g}" gradientUnits="userSpaceOnUse">
165
+ <stop stop-color="${t[2]}" />
166
+ <stop offset="1" stop-color="${t[3]}" />
167
+ </linearGradient>
168
+ </defs>
169
+ </svg>`},Z=["#92A1C6","#146A7C","#F0AB3D","#C271B4","#C20D90"],j={marble:z,pixel:D,ring:R,beam:v,bauhaus:C,sunset:P,geometric:v,abstract:C};function b(s={}){const{name:e="Clara Barton",colors:r=Z,title:a=!1,square:o=!1,size:n="40px",variant:t="marble"}=s;return(j[t]||z)({name:e,colors:r,title:a,square:o,size:n})}exports.boring=b;exports.default=b;
@@ -0,0 +1,29 @@
1
+ import { AvatarProps, AvatarVariant } from './types.js';
2
+ export type { AvatarProps, AvatarVariant };
3
+ /**
4
+ * Generate an SVG avatar
5
+ * @param props - Avatar configuration options
6
+ * @returns SVG string
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import boring from 'boring-avatars-vanilla';
11
+ *
12
+ * const svg = boring({
13
+ * name: 'John Doe',
14
+ * variant: 'beam',
15
+ * size: 40,
16
+ * colors: ['#92A1C6', '#146A7C', '#F0AB3D']
17
+ * });
18
+ *
19
+ * // Use in browser
20
+ * document.getElementById('avatar').innerHTML = svg;
21
+ *
22
+ * // Use in Node.js
23
+ * fs.writeFileSync('avatar.svg', svg);
24
+ * ```
25
+ */
26
+ declare function boring(props?: AvatarProps): string;
27
+ export { boring };
28
+ export default boring;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7D,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;AAe3C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,iBAAS,MAAM,CAAC,KAAK,GAAE,WAAgB,GAAG,MAAM,CAmB/C;AAED,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,370 @@
1
+ const S = (s) => {
2
+ let e = 0;
3
+ for (let r = 0; r < s.length; r++) {
4
+ const a = s.charCodeAt(r);
5
+ e = (e << 5) - e + a, e = e & e;
6
+ }
7
+ return Math.abs(e);
8
+ }, z = (s, e) => Math.floor(s / Math.pow(10, e) % 10), y = (s, e) => !(z(s, e) % 2), p = (s, e, r) => {
9
+ const a = s % e;
10
+ return r && z(s, r) % 2 === 0 ? -a : a;
11
+ }, w = (s, e, r) => e[s % r], E = (s) => {
12
+ s.slice(0, 1) === "#" && (s = s.slice(1));
13
+ const e = parseInt(s.substr(0, 2), 16), r = parseInt(s.substr(2, 2), 16), a = parseInt(s.substr(4, 2), 16);
14
+ return (e * 299 + r * 587 + a * 114) / 1e3 >= 128 ? "#000000" : "#FFFFFF";
15
+ };
16
+ let U = 0;
17
+ const k = () => `boring-avatar-${++U}-${Date.now().toString(36)}`, _ = 3, h = 80;
18
+ function B(s, e) {
19
+ const r = S(s), a = e.length;
20
+ return Array.from({ length: _ }, (n, t) => ({
21
+ color: w(r + t, e, a),
22
+ translateX: p(r * (t + 1), h / 10, 1),
23
+ translateY: p(r * (t + 1), h / 10, 2),
24
+ scale: 1.2 + p(r * (t + 1), h / 20) / 10,
25
+ rotate: p(r * (t + 1), 360, 1)
26
+ }));
27
+ }
28
+ const M = (s) => {
29
+ const { name: e, colors: r, title: a, square: o, size: n = "40px" } = s, t = B(e, r), i = k(), c = typeof n == "number" ? `${n}px` : n, f = o ? `<rect width="${h}" height="${h}" fill="#FFFFFF" />` : `<rect width="${h}" height="${h}" rx="${h * 2}" fill="#FFFFFF" />`;
30
+ return `<svg
31
+ viewBox="0 0 ${h} ${h}"
32
+ fill="none"
33
+ role="img"
34
+ xmlns="http://www.w3.org/2000/svg"
35
+ width="${c}"
36
+ height="${c}"
37
+ >
38
+ ${a ? `<title>${e}</title>` : ""}
39
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${h}" height="${h}">
40
+ ${f}
41
+ </mask>
42
+ <g mask="url(#${i})">
43
+ <rect width="${h}" height="${h}" fill="${t[0].color}" />
44
+ <path
45
+ filter="url(#filter_${i})"
46
+ d="M32.414 59.35L50.376 70.5H72.5v-71H33.728L26.5 13.381l19.057 27.08L32.414 59.35z"
47
+ fill="${t[1].color}"
48
+ transform="translate(${t[1].translateX} ${t[1].translateY}) rotate(${t[1].rotate} ${h / 2} ${h / 2}) scale(${t[2].scale})"
49
+ />
50
+ <path
51
+ filter="url(#filter_${i})"
52
+ style="mix-blend-mode: overlay"
53
+ d="M22.216 24L0 46.75l14.108 38.129L78 86l-3.081-59.276-22.378 4.005 12.972 20.186-23.35 27.395L22.215 24z"
54
+ fill="${t[2].color}"
55
+ transform="translate(${t[2].translateX} ${t[2].translateY}) rotate(${t[2].rotate} ${h / 2} ${h / 2}) scale(${t[2].scale})"
56
+ />
57
+ </g>
58
+ <defs>
59
+ <filter id="filter_${i}" filterUnits="userSpaceOnUse" colorInterpolationFilters="sRGB">
60
+ <feFlood floodOpacity="0" result="BackgroundImageFix" />
61
+ <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
62
+ <feGaussianBlur stdDeviation="7" result="effect1_foregroundBlur" />
63
+ </filter>
64
+ </defs>
65
+ </svg>`;
66
+ }, L = 64, u = 80;
67
+ function O(s, e) {
68
+ const r = S(s), a = e.length;
69
+ return Array.from(
70
+ { length: L },
71
+ (n, t) => w(r % (t + 1), e, a)
72
+ );
73
+ }
74
+ const T = (s) => {
75
+ const { name: e, colors: r, title: a, square: o, size: n = "40px" } = s, t = O(e, r), i = k(), c = typeof n == "number" ? `${n}px` : n, f = o ? `<rect width="${u}" height="${u}" fill="#FFFFFF" />` : `<rect width="${u}" height="${u}" rx="${u * 2}" fill="#FFFFFF" />`, m = [], F = [
76
+ [0, 0],
77
+ [20, 0],
78
+ [40, 0],
79
+ [60, 0],
80
+ [10, 0],
81
+ [30, 0],
82
+ [50, 0],
83
+ [70, 0],
84
+ [0, 10],
85
+ [0, 20],
86
+ [0, 30],
87
+ [0, 40],
88
+ [0, 50],
89
+ [0, 60],
90
+ [0, 70],
91
+ [20, 10],
92
+ [20, 20],
93
+ [20, 30],
94
+ [20, 40],
95
+ [20, 50],
96
+ [20, 60],
97
+ [20, 70],
98
+ [40, 10],
99
+ [40, 20],
100
+ [40, 30],
101
+ [40, 40],
102
+ [40, 50],
103
+ [40, 60],
104
+ [40, 70],
105
+ [60, 10],
106
+ [60, 20],
107
+ [60, 30],
108
+ [60, 40],
109
+ [60, 50],
110
+ [60, 60],
111
+ [60, 70],
112
+ [10, 10],
113
+ [10, 20],
114
+ [10, 30],
115
+ [10, 40],
116
+ [10, 50],
117
+ [10, 60],
118
+ [10, 70],
119
+ [30, 10],
120
+ [30, 20],
121
+ [30, 30],
122
+ [30, 40],
123
+ [30, 50],
124
+ [30, 60],
125
+ [30, 70],
126
+ [50, 10],
127
+ [50, 20],
128
+ [50, 30],
129
+ [50, 40],
130
+ [50, 50],
131
+ [50, 60],
132
+ [50, 70],
133
+ [70, 10],
134
+ [70, 20],
135
+ [70, 30],
136
+ [70, 40],
137
+ [70, 50],
138
+ [70, 60],
139
+ [70, 70]
140
+ ];
141
+ for (let x = 0; x < F.length; x++) {
142
+ const [I, b] = F[x];
143
+ m.push(` <rect x="${I}" y="${b}" width="10" height="10" fill="${t[x]}" />`);
144
+ }
145
+ return `<svg
146
+ viewBox="0 0 ${u} ${u}"
147
+ fill="none"
148
+ role="img"
149
+ xmlns="http://www.w3.org/2000/svg"
150
+ width="${c}"
151
+ height="${c}"
152
+ >
153
+ ${a ? `<title>${e}</title>` : ""}
154
+ <mask id="${i}" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="${u}" height="${u}">
155
+ ${f}
156
+ </mask>
157
+ <g mask="url(#${i})">
158
+ ${m.join(`
159
+ `)}
160
+ </g>
161
+ </svg>`;
162
+ }, d = 90, D = 5;
163
+ function A(s, e) {
164
+ const r = S(s), a = e.length, o = Array.from(
165
+ { length: D },
166
+ (t, i) => w(r + i, e, a)
167
+ ), n = [];
168
+ return n[0] = o[0], n[1] = o[1], n[2] = o[1], n[3] = o[2], n[4] = o[2], n[5] = o[3], n[6] = o[3], n[7] = o[0], n[8] = o[4], n;
169
+ }
170
+ const N = (s) => {
171
+ const { name: e, colors: r, title: a, square: o, size: n = "40px" } = s, t = A(e, r), i = k(), c = typeof n == "number" ? `${n}px` : n, f = o ? `<rect width="${d}" height="${d}" fill="#FFFFFF" />` : `<rect width="${d}" height="${d}" rx="${d * 2}" fill="#FFFFFF" />`;
172
+ return `<svg
173
+ viewBox="0 0 ${d} ${d}"
174
+ fill="none"
175
+ role="img"
176
+ xmlns="http://www.w3.org/2000/svg"
177
+ width="${c}"
178
+ height="${c}"
179
+ >
180
+ ${a ? `<title>${e}</title>` : ""}
181
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${d}" height="${d}">
182
+ ${f}
183
+ </mask>
184
+ <g mask="url(#${i})">
185
+ <path d="M0 0h90v45H0z" fill="${t[0]}" />
186
+ <path d="M0 45h90v45H0z" fill="${t[1]}" />
187
+ <path d="M83 45a38 38 0 00-76 0h76z" fill="${t[2]}" />
188
+ <path d="M83 45a38 38 0 01-76 0h76z" fill="${t[3]}" />
189
+ <path d="M77 45a32 32 0 10-64 0h64z" fill="${t[4]}" />
190
+ <path d="M77 45a32 32 0 11-64 0h64z" fill="${t[5]}" />
191
+ <path d="M71 45a26 26 0 00-52 0h52z" fill="${t[6]}" />
192
+ <path d="M71 45a26 26 0 01-52 0h52z" fill="${t[7]}" />
193
+ <circle cx="45" cy="45" r="23" fill="${t[8]}" />
194
+ </g>
195
+ </svg>`;
196
+ }, $ = 36;
197
+ function R(s, e) {
198
+ const r = S(s), a = e.length, o = w(r, e, a), n = p(r, 10, 1), t = n < 5 ? n + $ / 9 : n, i = p(r, 10, 2), c = i < 5 ? i + $ / 9 : i;
199
+ return {
200
+ wrapperColor: o,
201
+ faceColor: E(o),
202
+ backgroundColor: w(r + 13, e, a),
203
+ wrapperTranslateX: t,
204
+ wrapperTranslateY: c,
205
+ wrapperRotate: p(r, 360),
206
+ wrapperScale: 1 + p(r, $ / 12) / 10,
207
+ isMouthOpen: y(r, 2),
208
+ isCircle: y(r, 1),
209
+ eyeSpread: p(r, 5),
210
+ mouthSpread: p(r, 3),
211
+ faceRotate: p(r, 10, 3),
212
+ faceTranslateX: t > $ / 6 ? t / 2 : p(r, 8, 1),
213
+ faceTranslateY: c > $ / 6 ? c / 2 : p(r, 7, 2)
214
+ };
215
+ }
216
+ const v = (s) => {
217
+ const { name: e, colors: r, title: a, square: o, size: n = "40px" } = s, t = R(e, r), i = k(), c = typeof n == "number" ? `${n}px` : n, f = o ? `<rect width="${$}" height="${$}" fill="#FFFFFF" />` : `<rect width="${$}" height="${$}" rx="${$ * 2}" fill="#FFFFFF" />`, m = t.isMouthOpen ? `<path d="M15 ${19 + t.mouthSpread}c2 1 4 1 6 0" stroke="${t.faceColor}" fill="none" stroke-linecap="round" />` : `<path d="M13,${19 + t.mouthSpread} a1,0.75 0 0,0 10,0" fill="${t.faceColor}" />`, F = t.isCircle ? $ : $ / 6;
218
+ return `<svg
219
+ viewBox="0 0 ${$} ${$}"
220
+ fill="none"
221
+ role="img"
222
+ xmlns="http://www.w3.org/2000/svg"
223
+ width="${c}"
224
+ height="${c}"
225
+ >
226
+ ${a ? `<title>${e}</title>` : ""}
227
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${$}" height="${$}">
228
+ ${f}
229
+ </mask>
230
+ <g mask="url(#${i})">
231
+ <rect width="${$}" height="${$}" fill="${t.backgroundColor}" />
232
+ <rect
233
+ x="0"
234
+ y="0"
235
+ width="${$}"
236
+ height="${$}"
237
+ transform="translate(${t.wrapperTranslateX} ${t.wrapperTranslateY}) rotate(${t.wrapperRotate} ${$ / 2} ${$ / 2}) scale(${t.wrapperScale})"
238
+ fill="${t.wrapperColor}"
239
+ rx="${F}"
240
+ />
241
+ <g transform="translate(${t.faceTranslateX} ${t.faceTranslateY}) rotate(${t.faceRotate} ${$ / 2} ${$ / 2})">
242
+ ${m}
243
+ <rect x="${14 - t.eyeSpread}" y="14" width="1.5" height="2" rx="1" stroke="none" fill="${t.faceColor}" />
244
+ <rect x="${20 + t.eyeSpread}" y="14" width="1.5" height="2" rx="1" stroke="none" fill="${t.faceColor}" />
245
+ </g>
246
+ </g>
247
+ </svg>`;
248
+ }, X = 4, l = 80;
249
+ function Y(s, e) {
250
+ const r = S(s), a = e.length;
251
+ return Array.from({ length: X }, (n, t) => ({
252
+ color: w(r + t, e, a),
253
+ translateX: p(r * (t + 1), l / 2 - (t + 17), 1),
254
+ translateY: p(r * (t + 1), l / 2 - (t + 17), 2),
255
+ rotate: p(r * (t + 1), 360),
256
+ isSquare: y(r, 2)
257
+ }));
258
+ }
259
+ const C = (s) => {
260
+ const { name: e, colors: r, title: a, square: o, size: n = "40px" } = s, t = Y(e, r), i = k(), c = typeof n == "number" ? `${n}px` : n, f = o ? `<rect width="${l}" height="${l}" fill="#FFFFFF" />` : `<rect width="${l}" height="${l}" rx="${l * 2}" fill="#FFFFFF" />`, m = t[1].isSquare ? l : l / 8;
261
+ return `<svg
262
+ viewBox="0 0 ${l} ${l}"
263
+ fill="none"
264
+ role="img"
265
+ xmlns="http://www.w3.org/2000/svg"
266
+ width="${c}"
267
+ height="${c}"
268
+ >
269
+ ${a ? `<title>${e}</title>` : ""}
270
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${l}" height="${l}">
271
+ ${f}
272
+ </mask>
273
+ <g mask="url(#${i})">
274
+ <rect width="${l}" height="${l}" fill="${t[0].color}" />
275
+ <rect
276
+ x="${(l - 60) / 2}"
277
+ y="${(l - 20) / 2}"
278
+ width="${l}"
279
+ height="${m}"
280
+ fill="${t[1].color}"
281
+ transform="translate(${t[1].translateX} ${t[1].translateY}) rotate(${t[1].rotate} ${l / 2} ${l / 2})"
282
+ />
283
+ <circle
284
+ cx="${l / 2}"
285
+ cy="${l / 2}"
286
+ fill="${t[2].color}"
287
+ r="${l / 5}"
288
+ transform="translate(${t[2].translateX} ${t[2].translateY})"
289
+ />
290
+ <line
291
+ x1="0"
292
+ y1="${l / 2}"
293
+ x2="${l}"
294
+ y2="${l / 2}"
295
+ stroke-width="2"
296
+ stroke="${t[3].color}"
297
+ transform="translate(${t[3].translateX} ${t[3].translateY}) rotate(${t[3].rotate} ${l / 2} ${l / 2})"
298
+ />
299
+ </g>
300
+ </svg>`;
301
+ }, q = 4, g = 80;
302
+ function G(s, e) {
303
+ const r = S(s), a = e.length;
304
+ return Array.from(
305
+ { length: q },
306
+ (n, t) => w(r + t, e, a)
307
+ );
308
+ }
309
+ const H = (s) => {
310
+ const { name: e, colors: r, title: a, square: o, size: n = "40px" } = s, t = G(e, r), i = e.replace(/\s/g, ""), c = k(), f = `gradient_paint0_linear_${i}_${c}`, m = `gradient_paint1_linear_${i}_${c}`, F = typeof n == "number" ? `${n}px` : n, x = o ? `<rect width="${g}" height="${g}" fill="#FFFFFF" />` : `<rect width="${g}" height="${g}" rx="${g * 2}" fill="#FFFFFF" />`;
311
+ return `<svg
312
+ viewBox="0 0 ${g} ${g}"
313
+ fill="none"
314
+ role="img"
315
+ xmlns="http://www.w3.org/2000/svg"
316
+ width="${F}"
317
+ height="${F}"
318
+ >
319
+ ${a ? `<title>${e}</title>` : ""}
320
+ <mask id="${c}" maskUnits="userSpaceOnUse" x="0" y="0" width="${g}" height="${g}">
321
+ ${x}
322
+ </mask>
323
+ <g mask="url(#${c})">
324
+ <path fill="url(#${f})" d="M0 0h80v40H0z" />
325
+ <path fill="url(#${m})" d="M0 40h80v40H0z" />
326
+ </g>
327
+ <defs>
328
+ <linearGradient id="${f}" x1="${g / 2}" y1="0" x2="${g / 2}" y2="${g / 2}" gradientUnits="userSpaceOnUse">
329
+ <stop stop-color="${t[0]}" />
330
+ <stop offset="1" stop-color="${t[1]}" />
331
+ </linearGradient>
332
+ <linearGradient id="${m}" x1="${g / 2}" y1="${g / 2}" x2="${g / 2}" y2="${g}" gradientUnits="userSpaceOnUse">
333
+ <stop stop-color="${t[2]}" />
334
+ <stop offset="1" stop-color="${t[3]}" />
335
+ </linearGradient>
336
+ </defs>
337
+ </svg>`;
338
+ }, Z = ["#92A1C6", "#146A7C", "#F0AB3D", "#C271B4", "#C20D90"], P = {
339
+ marble: M,
340
+ pixel: T,
341
+ ring: N,
342
+ beam: v,
343
+ bauhaus: C,
344
+ sunset: H,
345
+ geometric: v,
346
+ // Deprecated, use 'beam'
347
+ abstract: C
348
+ // Deprecated, use 'bauhaus'
349
+ };
350
+ function j(s = {}) {
351
+ const {
352
+ name: e = "Clara Barton",
353
+ colors: r = Z,
354
+ title: a = !1,
355
+ square: o = !1,
356
+ size: n = "40px",
357
+ variant: t = "marble"
358
+ } = s;
359
+ return (P[t] || M)({
360
+ name: e,
361
+ colors: r,
362
+ title: a,
363
+ square: o,
364
+ size: n
365
+ });
366
+ }
367
+ export {
368
+ j as boring,
369
+ j as default
370
+ };
@@ -0,0 +1,169 @@
1
+ (function(w,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(w=typeof globalThis<"u"?globalThis:w||self,u(w.BoringAvatars={}))})(this,(function(w){"use strict";const u=s=>{let e=0;for(let r=0;r<s.length;r++){const o=s.charCodeAt(r);e=(e<<5)-e+o,e=e&e}return Math.abs(e)},C=(s,e)=>Math.floor(s/Math.pow(10,e)%10),v=(s,e)=>!(C(s,e)%2),g=(s,e,r)=>{const o=s%e;return r&&C(s,r)%2===0?-o:o},x=(s,e,r)=>e[s%r],E=s=>{s.slice(0,1)==="#"&&(s=s.slice(1));const e=parseInt(s.substr(0,2),16),r=parseInt(s.substr(2,2),16),o=parseInt(s.substr(4,2),16);return(e*299+r*587+o*114)/1e3>=128?"#000000":"#FFFFFF"};let _=0;const y=()=>`boring-avatar-${++_}-${Date.now().toString(36)}`,T=3,h=80;function U(s,e){const r=u(s),o=e.length;return Array.from({length:T},(n,t)=>({color:x(r+t,e,o),translateX:g(r*(t+1),h/10,1),translateY:g(r*(t+1),h/10,2),scale:1.2+g(r*(t+1),h/20)/10,rotate:g(r*(t+1),360,1)}))}const M=s=>{const{name:e,colors:r,title:o,square:a,size:n="40px"}=s,t=U(e,r),i=y(),c=typeof n=="number"?`${n}px`:n,p=a?`<rect width="${h}" height="${h}" fill="#FFFFFF" />`:`<rect width="${h}" height="${h}" rx="${h*2}" fill="#FFFFFF" />`;return`<svg
2
+ viewBox="0 0 ${h} ${h}"
3
+ fill="none"
4
+ role="img"
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ width="${c}"
7
+ height="${c}"
8
+ >
9
+ ${o?`<title>${e}</title>`:""}
10
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${h}" height="${h}">
11
+ ${p}
12
+ </mask>
13
+ <g mask="url(#${i})">
14
+ <rect width="${h}" height="${h}" fill="${t[0].color}" />
15
+ <path
16
+ filter="url(#filter_${i})"
17
+ d="M32.414 59.35L50.376 70.5H72.5v-71H33.728L26.5 13.381l19.057 27.08L32.414 59.35z"
18
+ fill="${t[1].color}"
19
+ transform="translate(${t[1].translateX} ${t[1].translateY}) rotate(${t[1].rotate} ${h/2} ${h/2}) scale(${t[2].scale})"
20
+ />
21
+ <path
22
+ filter="url(#filter_${i})"
23
+ style="mix-blend-mode: overlay"
24
+ d="M22.216 24L0 46.75l14.108 38.129L78 86l-3.081-59.276-22.378 4.005 12.972 20.186-23.35 27.395L22.215 24z"
25
+ fill="${t[2].color}"
26
+ transform="translate(${t[2].translateX} ${t[2].translateY}) rotate(${t[2].rotate} ${h/2} ${h/2}) scale(${t[2].scale})"
27
+ />
28
+ </g>
29
+ <defs>
30
+ <filter id="filter_${i}" filterUnits="userSpaceOnUse" colorInterpolationFilters="sRGB">
31
+ <feFlood floodOpacity="0" result="BackgroundImageFix" />
32
+ <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
33
+ <feGaussianBlur stdDeviation="7" result="effect1_foregroundBlur" />
34
+ </filter>
35
+ </defs>
36
+ </svg>`},B=64,d=80;function L(s,e){const r=u(s),o=e.length;return Array.from({length:B},(n,t)=>x(r%(t+1),e,o))}const O=s=>{const{name:e,colors:r,title:o,square:a,size:n="40px"}=s,t=L(e,r),i=y(),c=typeof n=="number"?`${n}px`:n,p=a?`<rect width="${d}" height="${d}" fill="#FFFFFF" />`:`<rect width="${d}" height="${d}" rx="${d*2}" fill="#FFFFFF" />`,F=[],S=[[0,0],[20,0],[40,0],[60,0],[10,0],[30,0],[50,0],[70,0],[0,10],[0,20],[0,30],[0,40],[0,50],[0,60],[0,70],[20,10],[20,20],[20,30],[20,40],[20,50],[20,60],[20,70],[40,10],[40,20],[40,30],[40,40],[40,50],[40,60],[40,70],[60,10],[60,20],[60,30],[60,40],[60,50],[60,60],[60,70],[10,10],[10,20],[10,30],[10,40],[10,50],[10,60],[10,70],[30,10],[30,20],[30,30],[30,40],[30,50],[30,60],[30,70],[50,10],[50,20],[50,30],[50,40],[50,50],[50,60],[50,70],[70,10],[70,20],[70,30],[70,40],[70,50],[70,60],[70,70]];for(let k=0;k<S.length;k++){const[j,V]=S[k];F.push(` <rect x="${j}" y="${V}" width="10" height="10" fill="${t[k]}" />`)}return`<svg
37
+ viewBox="0 0 ${d} ${d}"
38
+ fill="none"
39
+ role="img"
40
+ xmlns="http://www.w3.org/2000/svg"
41
+ width="${c}"
42
+ height="${c}"
43
+ >
44
+ ${o?`<title>${e}</title>`:""}
45
+ <mask id="${i}" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="${d}" height="${d}">
46
+ ${p}
47
+ </mask>
48
+ <g mask="url(#${i})">
49
+ ${F.join(`
50
+ `)}
51
+ </g>
52
+ </svg>`},m=90,D=5;function A(s,e){const r=u(s),o=e.length,a=Array.from({length:D},(t,i)=>x(r+i,e,o)),n=[];return n[0]=a[0],n[1]=a[1],n[2]=a[1],n[3]=a[2],n[4]=a[2],n[5]=a[3],n[6]=a[3],n[7]=a[0],n[8]=a[4],n}const N=s=>{const{name:e,colors:r,title:o,square:a,size:n="40px"}=s,t=A(e,r),i=y(),c=typeof n=="number"?`${n}px`:n,p=a?`<rect width="${m}" height="${m}" fill="#FFFFFF" />`:`<rect width="${m}" height="${m}" rx="${m*2}" fill="#FFFFFF" />`;return`<svg
53
+ viewBox="0 0 ${m} ${m}"
54
+ fill="none"
55
+ role="img"
56
+ xmlns="http://www.w3.org/2000/svg"
57
+ width="${c}"
58
+ height="${c}"
59
+ >
60
+ ${o?`<title>${e}</title>`:""}
61
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${m}" height="${m}">
62
+ ${p}
63
+ </mask>
64
+ <g mask="url(#${i})">
65
+ <path d="M0 0h90v45H0z" fill="${t[0]}" />
66
+ <path d="M0 45h90v45H0z" fill="${t[1]}" />
67
+ <path d="M83 45a38 38 0 00-76 0h76z" fill="${t[2]}" />
68
+ <path d="M83 45a38 38 0 01-76 0h76z" fill="${t[3]}" />
69
+ <path d="M77 45a32 32 0 10-64 0h64z" fill="${t[4]}" />
70
+ <path d="M77 45a32 32 0 11-64 0h64z" fill="${t[5]}" />
71
+ <path d="M71 45a26 26 0 00-52 0h52z" fill="${t[6]}" />
72
+ <path d="M71 45a26 26 0 01-52 0h52z" fill="${t[7]}" />
73
+ <circle cx="45" cy="45" r="23" fill="${t[8]}" />
74
+ </g>
75
+ </svg>`},$=36;function R(s,e){const r=u(s),o=e.length,a=x(r,e,o),n=g(r,10,1),t=n<5?n+$/9:n,i=g(r,10,2),c=i<5?i+$/9:i;return{wrapperColor:a,faceColor:E(a),backgroundColor:x(r+13,e,o),wrapperTranslateX:t,wrapperTranslateY:c,wrapperRotate:g(r,360),wrapperScale:1+g(r,$/12)/10,isMouthOpen:v(r,2),isCircle:v(r,1),eyeSpread:g(r,5),mouthSpread:g(r,3),faceRotate:g(r,10,3),faceTranslateX:t>$/6?t/2:g(r,8,1),faceTranslateY:c>$/6?c/2:g(r,7,2)}}const b=s=>{const{name:e,colors:r,title:o,square:a,size:n="40px"}=s,t=R(e,r),i=y(),c=typeof n=="number"?`${n}px`:n,p=a?`<rect width="${$}" height="${$}" fill="#FFFFFF" />`:`<rect width="${$}" height="${$}" rx="${$*2}" fill="#FFFFFF" />`,F=t.isMouthOpen?`<path d="M15 ${19+t.mouthSpread}c2 1 4 1 6 0" stroke="${t.faceColor}" fill="none" stroke-linecap="round" />`:`<path d="M13,${19+t.mouthSpread} a1,0.75 0 0,0 10,0" fill="${t.faceColor}" />`,S=t.isCircle?$:$/6;return`<svg
76
+ viewBox="0 0 ${$} ${$}"
77
+ fill="none"
78
+ role="img"
79
+ xmlns="http://www.w3.org/2000/svg"
80
+ width="${c}"
81
+ height="${c}"
82
+ >
83
+ ${o?`<title>${e}</title>`:""}
84
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${$}" height="${$}">
85
+ ${p}
86
+ </mask>
87
+ <g mask="url(#${i})">
88
+ <rect width="${$}" height="${$}" fill="${t.backgroundColor}" />
89
+ <rect
90
+ x="0"
91
+ y="0"
92
+ width="${$}"
93
+ height="${$}"
94
+ transform="translate(${t.wrapperTranslateX} ${t.wrapperTranslateY}) rotate(${t.wrapperRotate} ${$/2} ${$/2}) scale(${t.wrapperScale})"
95
+ fill="${t.wrapperColor}"
96
+ rx="${S}"
97
+ />
98
+ <g transform="translate(${t.faceTranslateX} ${t.faceTranslateY}) rotate(${t.faceRotate} ${$/2} ${$/2})">
99
+ ${F}
100
+ <rect x="${14-t.eyeSpread}" y="14" width="1.5" height="2" rx="1" stroke="none" fill="${t.faceColor}" />
101
+ <rect x="${20+t.eyeSpread}" y="14" width="1.5" height="2" rx="1" stroke="none" fill="${t.faceColor}" />
102
+ </g>
103
+ </g>
104
+ </svg>`},X=4,l=80;function Y(s,e){const r=u(s),o=e.length;return Array.from({length:X},(n,t)=>({color:x(r+t,e,o),translateX:g(r*(t+1),l/2-(t+17),1),translateY:g(r*(t+1),l/2-(t+17),2),rotate:g(r*(t+1),360),isSquare:v(r,2)}))}const z=s=>{const{name:e,colors:r,title:o,square:a,size:n="40px"}=s,t=Y(e,r),i=y(),c=typeof n=="number"?`${n}px`:n,p=a?`<rect width="${l}" height="${l}" fill="#FFFFFF" />`:`<rect width="${l}" height="${l}" rx="${l*2}" fill="#FFFFFF" />`,F=t[1].isSquare?l:l/8;return`<svg
105
+ viewBox="0 0 ${l} ${l}"
106
+ fill="none"
107
+ role="img"
108
+ xmlns="http://www.w3.org/2000/svg"
109
+ width="${c}"
110
+ height="${c}"
111
+ >
112
+ ${o?`<title>${e}</title>`:""}
113
+ <mask id="${i}" maskUnits="userSpaceOnUse" x="0" y="0" width="${l}" height="${l}">
114
+ ${p}
115
+ </mask>
116
+ <g mask="url(#${i})">
117
+ <rect width="${l}" height="${l}" fill="${t[0].color}" />
118
+ <rect
119
+ x="${(l-60)/2}"
120
+ y="${(l-20)/2}"
121
+ width="${l}"
122
+ height="${F}"
123
+ fill="${t[1].color}"
124
+ transform="translate(${t[1].translateX} ${t[1].translateY}) rotate(${t[1].rotate} ${l/2} ${l/2})"
125
+ />
126
+ <circle
127
+ cx="${l/2}"
128
+ cy="${l/2}"
129
+ fill="${t[2].color}"
130
+ r="${l/5}"
131
+ transform="translate(${t[2].translateX} ${t[2].translateY})"
132
+ />
133
+ <line
134
+ x1="0"
135
+ y1="${l/2}"
136
+ x2="${l}"
137
+ y2="${l/2}"
138
+ stroke-width="2"
139
+ stroke="${t[3].color}"
140
+ transform="translate(${t[3].translateX} ${t[3].translateY}) rotate(${t[3].rotate} ${l/2} ${l/2})"
141
+ />
142
+ </g>
143
+ </svg>`},q=4,f=80;function G(s,e){const r=u(s),o=e.length;return Array.from({length:q},(n,t)=>x(r+t,e,o))}const H=s=>{const{name:e,colors:r,title:o,square:a,size:n="40px"}=s,t=G(e,r),i=e.replace(/\s/g,""),c=y(),p=`gradient_paint0_linear_${i}_${c}`,F=`gradient_paint1_linear_${i}_${c}`,S=typeof n=="number"?`${n}px`:n,k=a?`<rect width="${f}" height="${f}" fill="#FFFFFF" />`:`<rect width="${f}" height="${f}" rx="${f*2}" fill="#FFFFFF" />`;return`<svg
144
+ viewBox="0 0 ${f} ${f}"
145
+ fill="none"
146
+ role="img"
147
+ xmlns="http://www.w3.org/2000/svg"
148
+ width="${S}"
149
+ height="${S}"
150
+ >
151
+ ${o?`<title>${e}</title>`:""}
152
+ <mask id="${c}" maskUnits="userSpaceOnUse" x="0" y="0" width="${f}" height="${f}">
153
+ ${k}
154
+ </mask>
155
+ <g mask="url(#${c})">
156
+ <path fill="url(#${p})" d="M0 0h80v40H0z" />
157
+ <path fill="url(#${F})" d="M0 40h80v40H0z" />
158
+ </g>
159
+ <defs>
160
+ <linearGradient id="${p}" x1="${f/2}" y1="0" x2="${f/2}" y2="${f/2}" gradientUnits="userSpaceOnUse">
161
+ <stop stop-color="${t[0]}" />
162
+ <stop offset="1" stop-color="${t[1]}" />
163
+ </linearGradient>
164
+ <linearGradient id="${F}" x1="${f/2}" y1="${f/2}" x2="${f/2}" y2="${f}" gradientUnits="userSpaceOnUse">
165
+ <stop stop-color="${t[2]}" />
166
+ <stop offset="1" stop-color="${t[3]}" />
167
+ </linearGradient>
168
+ </defs>
169
+ </svg>`},P=["#92A1C6","#146A7C","#F0AB3D","#C271B4","#C20D90"],Z={marble:M,pixel:O,ring:N,beam:b,bauhaus:z,sunset:H,geometric:b,abstract:z};function I(s={}){const{name:e="Clara Barton",colors:r=P,title:o=!1,square:a=!1,size:n="40px",variant:t="marble"}=s;return(Z[t]||M)({name:e,colors:r,title:o,square:a,size:n})}w.boring=I,w.default=I,Object.defineProperties(w,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
@@ -0,0 +1,28 @@
1
+ export type AvatarVariant = 'pixel' | 'bauhaus' | 'ring' | 'beam' | 'sunset' | 'marble' | 'geometric' | 'abstract';
2
+ export interface AvatarProps {
3
+ /** The name to generate the avatar from */
4
+ name?: string;
5
+ /** Array of colors to use in the avatar */
6
+ colors?: string[];
7
+ /** Include a title element in the SVG */
8
+ title?: boolean;
9
+ /** Make the avatar square instead of round */
10
+ square?: boolean;
11
+ /** Size of the avatar (number for pixels, or string with unit) */
12
+ size?: number | string;
13
+ /** Variant style of the avatar */
14
+ variant?: AvatarVariant;
15
+ }
16
+ export interface AvatarResult {
17
+ /** The SVG string */
18
+ svg: string;
19
+ /** The generated avatar data (for advanced use) */
20
+ data: {
21
+ name: string;
22
+ colors: string[];
23
+ size: string;
24
+ square: boolean;
25
+ variant: AvatarVariant;
26
+ };
27
+ }
28
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC;AAEnH,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,yCAAyC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,kCAAkC;IAClC,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,qBAAqB;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,aAAa,CAAC;KACxB,CAAC;CACH"}
@@ -0,0 +1,11 @@
1
+ export declare const hashCode: (name: string) => number;
2
+ export declare const getModulus: (num: number, max: number) => number;
3
+ export declare const getDigit: (number: number, ntn: number) => number;
4
+ export declare const getBoolean: (number: number, ntn: number) => boolean;
5
+ export declare const getAngle: (x: number, y: number) => number;
6
+ export declare const getUnit: (number: number, range: number, index?: number) => number;
7
+ export declare const getRandomColor: (number: number, colors: string[], range: number) => string;
8
+ export declare const getContrast: (hexcolor: string) => string;
9
+ export declare const generateId: () => string;
10
+ export declare const normalizeSize: (size: number | string | undefined) => string;
11
+ //# sourceMappingURL=utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,KAAG,MAQvC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,MAErD,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAEtD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,OAExD,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAE/C,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,EAAE,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,MAMvE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,EAAE,QAAQ,MAAM,EAAE,EAAE,OAAO,MAAM,KAAG,MAEhF,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,MAgB9C,CAAC;AAIF,eAAO,MAAM,UAAU,QAAO,MAE7B,CAAC;AAGF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,GAAG,MAAM,GAAG,SAAS,KAAG,MAIjE,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface BauhausOptions {
2
+ name: string;
3
+ colors: string[];
4
+ title?: boolean;
5
+ square?: boolean;
6
+ size?: number | string;
7
+ }
8
+ export declare const generateBauhaus: (options: BauhausOptions) => string;
9
+ //# sourceMappingURL=bauhaus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bauhaus.d.ts","sourceRoot":"","sources":["../../src/variants/bauhaus.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,GAAI,SAAS,cAAc,KAAG,MAoDzD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface BeamOptions {
2
+ name: string;
3
+ colors: string[];
4
+ title?: boolean;
5
+ square?: boolean;
6
+ size?: number | string;
7
+ }
8
+ export declare const generateBeam: (options: BeamOptions) => string;
9
+ //# sourceMappingURL=beam.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beam.d.ts","sourceRoot":"","sources":["../../src/variants/beam.ts"],"names":[],"mappings":"AAoDA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,GAAI,SAAS,WAAW,KAAG,MA8CnD,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { generateMarble, type MarbleOptions } from './marble.js';
2
+ export { generatePixel, type PixelOptions } from './pixel.js';
3
+ export { generateRing, type RingOptions } from './ring.js';
4
+ export { generateBeam, type BeamOptions } from './beam.js';
5
+ export { generateBauhaus, type BauhausOptions } from './bauhaus.js';
6
+ export { generateSunset, type SunsetOptions } from './sunset.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/variants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface MarbleOptions {
2
+ name: string;
3
+ colors: string[];
4
+ title?: boolean;
5
+ square?: boolean;
6
+ size?: number | string;
7
+ }
8
+ export declare const generateMarble: (options: MarbleOptions) => string;
9
+ //# sourceMappingURL=marble.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marble.d.ts","sourceRoot":"","sources":["../../src/variants/marble.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,GAAI,SAAS,aAAa,KAAG,MA8CvD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface PixelOptions {
2
+ name: string;
3
+ colors: string[];
4
+ title?: boolean;
5
+ square?: boolean;
6
+ size?: number | string;
7
+ }
8
+ export declare const generatePixel: (options: PixelOptions) => string;
9
+ //# sourceMappingURL=pixel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pixel.d.ts","sourceRoot":"","sources":["../../src/variants/pixel.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,aAAa,GAAI,SAAS,YAAY,KAAG,MA8CrD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface RingOptions {
2
+ name: string;
3
+ colors: string[];
4
+ title?: boolean;
5
+ square?: boolean;
6
+ size?: number | string;
7
+ }
8
+ export declare const generateRing: (options: RingOptions) => string;
9
+ //# sourceMappingURL=ring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ring.d.ts","sourceRoot":"","sources":["../../src/variants/ring.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,GAAI,SAAS,WAAW,KAAG,MAkCnD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface SunsetOptions {
2
+ name: string;
3
+ colors: string[];
4
+ title?: boolean;
5
+ square?: boolean;
6
+ size?: number | string;
7
+ }
8
+ export declare const generateSunset: (options: SunsetOptions) => string;
9
+ //# sourceMappingURL=sunset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sunset.d.ts","sourceRoot":"","sources":["../../src/variants/sunset.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,GAAI,SAAS,aAAa,KAAG,MAwCvD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "boring-avatars-vanilla",
3
+ "version": "1.0.0",
4
+ "description": "Boring avatars as a vanilla JavaScript library, SVG-based avatars from any username and color palette. Works in both browsers and Node.js server-side rendering.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc && vite build",
21
+ "test": "vitest",
22
+ "test:run": "vitest run",
23
+ "dev": "vite"
24
+ },
25
+ "keywords": [
26
+ "boring-avatars",
27
+ "boring",
28
+ "avatar",
29
+ "svg",
30
+ "vanilla",
31
+ "javascript",
32
+ "nodejs",
33
+ "browser"
34
+ ],
35
+ "license": "MIT",
36
+ "devDependencies": {
37
+ "@types/node": "^22.0.0",
38
+ "typescript": "~5.8.3",
39
+ "vite": "^7.0.0",
40
+ "vite-plugin-dts": "^4.5.4",
41
+ "vitest": "^3.0.0"
42
+ },
43
+ "repository": "git@github.com:boringdesigners/boring-avatars.git"
44
+ }