@firecms/neat
Version:
Beautiful 3D gradients for your website
398 lines (318 loc) • 19.4 kB
JavaScript
(function(u,d){typeof exports=="object"&&typeof module<"u"?d(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],d):(u=typeof globalThis<"u"?globalThis:u||self,d(u.FireCMS={},u.THREE))})(this,function(u,d){"use strict";function T(t){if(t&&t.__esModule)return t;const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const o in t)if(o!=="default"){const i=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(e,o,i.get?i:{enumerable:!0,get:()=>t[o]})}}return e.default=t,Object.freeze(e)}const n=T(d),_=50,g=80,D=!0,b=5,k=new n.Clock,F=V();class B{_ref;_speed=-1;_horizontalPressure=-1;_verticalPressure=-1;_waveFrequencyX=-1;_waveFrequencyY=-1;_waveAmplitude=-1;_shadows=-1;_highlights=-1;_saturation=-1;_brightness=-1;_grainScale=-1;_grainIntensity=-1;_grainSparsity=-1;_grainSpeed=-1;_colorBlending=-1;_colors=[];_wireframe=!1;_backgroundColor="#FFFFFF";_backgroundAlpha=1;requestRef=-1;sizeObserver;sceneState;_yOffset=0;constructor(e){const{ref:o,speed:i=4,horizontalPressure:s=3,verticalPressure:a=3,waveFrequencyX:c=5,waveFrequencyY:f=5,waveAmplitude:h=3,colors:l,highlights:v=4,shadows:y=4,colorSaturation:z=0,colorBrightness:P=1,colorBlending:S=5,grainScale:Y=2,grainIntensity:W=.55,grainSparsity:X=0,grainSpeed:J=.1,wireframe:Q=!1,backgroundColor:Z="#FFFFFF",backgroundAlpha:$=1,resolution:ee=1,seed:E,yOffset:te=0}=e;this._ref=o,this.destroy=this.destroy.bind(this),this._initScene=this._initScene.bind(this),this._buildMaterial=this._buildMaterial.bind(this),this.speed=i,this.horizontalPressure=s,this.verticalPressure=a,this.waveFrequencyX=c,this.waveFrequencyY=f,this.waveAmplitude=h,this.colorBlending=S,this.grainScale=Y,this.grainIntensity=W,this.grainSparsity=X,this.grainSpeed=J,this.colors=l,this.shadows=y,this.highlights=v,this.colorSaturation=z,this.colorBrightness=P,this.wireframe=Q,this.backgroundColor=Z,this.backgroundAlpha=$,this.yOffset=te,this.sceneState=this._initScene(ee);let C=E!==void 0?E:U();const R=()=>{const{renderer:m,camera:x,scene:p,meshes:w}=this.sceneState;Math.floor(C*10)%5===0&&G(o),m.setClearColor(this._backgroundColor,this._backgroundAlpha),w.forEach(r=>{const re=this._ref.width,ie=this._ref.height,ne=[...this._colors.map(q=>{let j=new n.Color;return j.setStyle(q.color,""),{is_active:q.enabled,color:j,influence:q.influence}}),...Array.from({length:b-this._colors.length}).map(()=>({is_active:!1,color:new n.Color(0)}))];C+=k.getDelta()*this._speed,r.material.uniforms.u_time.value=C,r.material.uniforms.u_resolution={value:new n.Vector2(re,ie)},r.material.uniforms.u_color_pressure={value:new n.Vector2(this._horizontalPressure,this._verticalPressure)},r.material.uniforms.u_wave_frequency_x={value:this._waveFrequencyX},r.material.uniforms.u_wave_frequency_y={value:this._waveFrequencyY},r.material.uniforms.u_wave_amplitude={value:this._waveAmplitude},r.material.uniforms.u_plane_width={value:_},r.material.uniforms.u_plane_height={value:g},r.material.uniforms.u_color_blending={value:this._colorBlending},r.material.uniforms.u_colors={value:ne},r.material.uniforms.u_colors_count={value:b},r.material.uniforms.u_shadows={value:this._shadows},r.material.uniforms.u_highlights={value:this._highlights},r.material.uniforms.u_saturation={value:this._saturation},r.material.uniforms.u_brightness={value:this._brightness},r.material.uniforms.u_grain_intensity={value:this._grainIntensity},r.material.uniforms.u_grain_sparsity={value:this._grainSparsity},r.material.uniforms.u_grain_speed={value:this._grainSpeed},r.material.uniforms.u_grain_scale={value:this._grainScale},r.material.uniforms.u_y_offset={value:this._yOffset},r.material.wireframe=this._wireframe}),m.render(p,x),this.requestRef=requestAnimationFrame(R)},oe=()=>{const{renderer:m}=this.sceneState,x=m.domElement,p=x.clientWidth,w=x.clientHeight;this.sceneState.renderer.setSize(p,w,!1),A(this.sceneState.camera,p,w)};this.sizeObserver=new ResizeObserver(m=>{oe()}),this.sizeObserver.observe(o),R()}destroy(){this&&(cancelAnimationFrame(this.requestRef),this.sizeObserver.disconnect())}downloadAsPNG(e="neat.png"){console.log("Downloading as PNG",this._ref);const o=this._ref.toDataURL("image/png");console.log("data",o),H(o,e)}set speed(e){this._speed=e/20}set horizontalPressure(e){this._horizontalPressure=e/4}set verticalPressure(e){this._verticalPressure=e/4}set waveFrequencyX(e){this._waveFrequencyX=e*.04}set waveFrequencyY(e){this._waveFrequencyY=e*.04}set waveAmplitude(e){this._waveAmplitude=e*.75}set colors(e){this._colors=e}set highlights(e){this._highlights=e/100}set shadows(e){this._shadows=e/100}set colorSaturation(e){this._saturation=e/10}set colorBrightness(e){this._brightness=e}set colorBlending(e){this._colorBlending=e/10}set grainScale(e){this._grainScale=e==0?1:e}set grainIntensity(e){this._grainIntensity=e}set grainSparsity(e){this._grainSparsity=e}set grainSpeed(e){this._grainSpeed=e}set wireframe(e){this._wireframe=e}set resolution(e){this.sceneState=this._initScene(e)}set backgroundColor(e){this._backgroundColor=e}set backgroundAlpha(e){this._backgroundAlpha=e}set yOffset(e){this._yOffset=e}_initScene(e){const o=this._ref.width,i=this._ref.height,s=new n.WebGLRenderer({alpha:!0,preserveDrawingBuffer:!0,canvas:this._ref});s.setClearColor(16711680,.5),s.setSize(o,i,!1);const a=[],c=new n.Scene,f=this._buildMaterial(o,i),h=new n.PlaneGeometry(_,g,240*e,240*e),l=new n.Mesh(h,f);l.rotation.x=-Math.PI/3.5,l.position.z=-1,a.push(l),c.add(l);const v=new n.OrthographicCamera(0,0,0,0,0,0);return v.position.z=5,A(v,o,i),{renderer:s,camera:v,scene:c,meshes:a,resolution:e}}_buildMaterial(e,o){const i=[...this._colors.map(c=>({is_active:c.enabled,color:new n.Color(c.color),influence:c.influence})),...Array.from({length:b-this._colors.length}).map(()=>({is_active:!1,color:new n.Color(0)}))],s={u_time:{value:0},u_color_pressure:{value:new n.Vector2(this._horizontalPressure,this._verticalPressure)},u_wave_frequency_x:{value:this._waveFrequencyX},u_wave_frequency_y:{value:this._waveFrequencyY},u_wave_amplitude:{value:this._waveAmplitude},u_resolution:{value:new n.Vector2(e,o)},u_colors:{value:i},u_colors_count:{value:this._colors.length},u_plane_width:{value:_},u_plane_height:{value:g},u_shadows:{value:this._shadows},u_highlights:{value:this._highlights},u_grain_intensity:{value:this._grainIntensity},u_grain_sparsity:{value:this._grainSparsity},u_grain_scale:{value:this._grainScale},u_grain_speed:{value:this._grainSpeed}},a=new n.ShaderMaterial({uniforms:s,vertexShader:M()+O()+I()+K(),fragmentShader:M()+I()+O()+L()});return a.wireframe=D,a}}function A(t,e,o){const a=e*o/1e6*_*g/1.5,c=e/o,f=Math.sqrt(a*c),h=a/f,l=-_/2,v=Math.min((l+f)/1.5,_/2),y=g/4,z=Math.max((y-h)/2,-g/4),P=-100,S=1e3;t instanceof n.OrthographicCamera?(t.left=l,t.right=v,t.top=y,t.bottom=z,t.near=P,t.far=S,t.updateProjectionMatrix()):t instanceof n.PerspectiveCamera&&(t.aspect=e/o,t.updateProjectionMatrix())}function K(){return`
void main() {
vUv = uv;
v_displacement_amount = cnoise( vec3(
u_wave_frequency_x * position.x + u_time,
u_wave_frequency_y * position.y + u_time,
u_time
));
vec3 color;
// float t = mod(u_base_color, 100.0);
color = u_colors[0].color;
// Apply y_offset to the noise coordinates
vec2 noise_cord = vUv * u_color_pressure;
// Apply the y-offset to shift the pattern vertically (1:1 pixel ratio)
// Scale the offset to match the UV coordinate space
float scaledOffset = u_y_offset / u_resolution.y;
noise_cord.y -= scaledOffset;
const float minNoise = .0;
const float maxNoise = .9;
for (int i = 1; i < u_colors_count; i++) {
if(u_colors[i].is_active == 1.0){
float noiseFlow = (1. + float(i)) / 30.;
float noiseSpeed = (1. + float(i)) * 0.11;
float noiseSeed = 13. + float(i) * 7.;
int reverseIndex = u_colors_count - i;
float noise = snoise(
vec3(
noise_cord.x * u_color_pressure.x + u_time * noiseFlow * 2.,
noise_cord.y * u_color_pressure.y,
u_time * noiseSpeed
) + noiseSeed
) - (.1 * float(i)) + (.5 * u_color_blending);
noise = clamp(minNoise, maxNoise + float(i) * 0.02, noise);
vec3 nextColor = u_colors[i].color;
color = mix(color, nextColor, smoothstep(0.0, u_color_blending, noise));
}
}
v_color = color;
vec3 newPosition = position + normal * v_displacement_amount * u_wave_amplitude;
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
v_new_position = gl_Position;
}
`}function L(){return`
float random(vec2 p) {
return fract(sin(dot(p, vec2(12.9898,78.233))) * 43758.5453);
}
float fbm(vec3 x) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
for (int i = 0; i < 4; i++) {
value += amplitude * snoise(x * frequency);
frequency *= 2.0;
amplitude *= 0.5;
}
return value;
}
void main() {
vec3 color = v_color;
color += pow(v_displacement_amount, 1.0) * u_highlights;
color -= pow(1.0 - v_displacement_amount, 2.0) * u_shadows;
color = saturation(color, 1.0 + u_saturation);
color = color * u_brightness;
// Generate grain using fbm
vec2 noiseCoords = gl_FragCoord.xy / u_grain_scale;
float grain = (u_grain_speed != 0.0) ? fbm(vec3(noiseCoords, u_time * u_grain_speed)) : fbm(vec3(noiseCoords, 0.0));
// Center the grain around zero
grain = grain * 0.5 + 0.5;
grain -= 0.5;
// Add sparsity control
grain = (grain > u_grain_sparsity) ? grain : 0.0;
// Apply grain intensity
grain *= u_grain_intensity;
// Add grain to color
color += vec3(grain);
gl_FragColor = vec4(color, 1.0);
}
`}const M=()=>`
precision highp float;
struct Color {
float is_active;
vec3 color;
float value;
};
uniform float u_grain_intensity;
uniform float u_grain_sparsity;
uniform float u_grain_scale;
uniform float u_grain_speed;
uniform float u_time;
uniform float u_wave_amplitude;
uniform float u_wave_frequency_x;
uniform float u_wave_frequency_y;
uniform vec2 u_color_pressure;
uniform float u_plane_width;
uniform float u_plane_height;
uniform float u_shadows;
uniform float u_highlights;
uniform float u_saturation;
uniform float u_brightness;
uniform float u_color_blending;
uniform int u_colors_count;
uniform Color u_colors[5];
uniform vec2 u_resolution;
uniform float u_y_offset;
varying vec2 vUv;
varying vec4 v_new_position;
varying vec3 v_color;
varying float v_displacement_amount;
`,O=()=>`
vec3 mod289(vec3 x)
{
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 mod289(vec4 x)
{
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 permute(vec4 x)
{
return mod289(((x*34.0)+1.0)*x);
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
vec3 fade(vec3 t) {
return t*t*t*(t*(t*6.0-15.0)+10.0);
}
float snoise(vec3 v)
{
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy) );
vec3 x0 = v - i + dot(i, C.xxx) ;
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx;
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod289(i);
vec4 p = permute( permute( permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0)*2.0 + 1.0;
vec4 s1 = floor(b1)*2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
vec3 p0 = vec3(a0.xy,h.x);
vec3 p1 = vec3(a0.zw,h.y);
vec3 p2 = vec3(a1.xy,h.z);
vec3 p3 = vec3(a1.zw,h.w);
//Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
dot(p2,x2), dot(p3,x3) ) );
}
// Classic Perlin noise
float cnoise(vec3 P)
{
vec3 Pi0 = floor(P); // Integer part for indexing
vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
Pi0 = mod289(Pi0);
Pi1 = mod289(Pi1);
vec3 Pf0 = fract(P); // Fractional part for interpolation
vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
vec4 iy = vec4(Pi0.yy, Pi1.yy);
vec4 iz0 = Pi0.zzzz;
vec4 iz1 = Pi1.zzzz;
vec4 ixy = permute(permute(ix) + iy);
vec4 ixy0 = permute(ixy + iz0);
vec4 ixy1 = permute(ixy + iz1);
vec4 gx0 = ixy0 * (1.0 / 7.0);
vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
gx0 = fract(gx0);
vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
vec4 sz0 = step(gz0, vec4(0.0));
gx0 -= sz0 * (step(0.0, gx0) - 0.5);
gy0 -= sz0 * (step(0.0, gy0) - 0.5);
vec4 gx1 = ixy1 * (1.0 / 7.0);
vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
gx1 = fract(gx1);
vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
vec4 sz1 = step(gz1, vec4(0.0));
gx1 -= sz1 * (step(0.0, gx1) - 0.5);
gy1 -= sz1 * (step(0.0, gy1) - 0.5);
vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
g000 *= norm0.x;
g010 *= norm0.y;
g100 *= norm0.z;
g110 *= norm0.w;
vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
g001 *= norm1.x;
g011 *= norm1.y;
g101 *= norm1.z;
g111 *= norm1.w;
float n000 = dot(g000, Pf0);
float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
float n111 = dot(g111, Pf1);
vec3 fade_xyz = fade(Pf0);
vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
return 2.2 * n_xyz;
}
// YUV to RGB matrix
mat3 yuv2rgb = mat3(1.0, 0.0, 1.13983,
1.0, -0.39465, -0.58060,
1.0, 2.03211, 0.0);
// RGB to YUV matrix
mat3 rgb2yuv = mat3(0.2126, 0.7152, 0.0722,
-0.09991, -0.33609, 0.43600,
0.615, -0.5586, -0.05639);
vec3 oklab2rgb(vec3 linear)
{
const mat3 im1 = mat3(0.4121656120, 0.2118591070, 0.0883097947,
0.5362752080, 0.6807189584, 0.2818474174,
0.0514575653, 0.1074065790, 0.6302613616);
const mat3 im2 = mat3(+0.2104542553, +1.9779984951, +0.0259040371,
+0.7936177850, -2.4285922050, +0.7827717662,
-0.0040720468, +0.4505937099, -0.8086757660);
vec3 lms = im1 * linear;
return im2 * (sign(lms) * pow(abs(lms), vec3(1.0/3.0)));
}
vec3 rgb2oklab(vec3 oklab)
{
const mat3 m1 = mat3(+1.000000000, +1.000000000, +1.000000000,
+0.396337777, -0.105561346, -0.089484178,
+0.215803757, -0.063854173, -1.291485548);
const mat3 m2 = mat3(+4.076724529, -1.268143773, -0.004111989,
-3.307216883, +2.609332323, -0.703476310,
+0.230759054, -0.341134429, +1.706862569);
vec3 lms = m1 * oklab;
return m2 * (lms * lms * lms);
}
`,I=()=>`
vec3 saturation(vec3 rgb, float adjustment) {
const vec3 W = vec3(0.2125, 0.7154, 0.0721);
vec3 intensity = vec3(dot(rgb, W));
return mix(intensity, rgb, adjustment);
}
float saturation(vec3 rgb)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g));
vec4 q = mix(vec4(p.xyw, rgb.r), vec4(rgb.r, p.yzx), step(p.x, rgb.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return abs(6.0 * d + e);
}
// get saturation of a color in values between 0 and 1
float getSaturation(vec3 color) {
float max = max(color.r, max(color.g, color.b));
float min = min(color.r, min(color.g, color.b));
return (max - min) / max;
}
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
`,N=t=>{t.id=F,t.href="https://neat.firecms.co",t.target="_blank",t.style.position="absolute",t.style.display="block",t.style.bottom="0",t.style.right="0",t.style.padding="10px",t.style.color="#dcdcdc",t.style.opacity="0.8",t.style.fontFamily="sans-serif",t.style.fontSize="16px",t.style.fontWeight="bold",t.style.textDecoration="none",t.style.zIndex="10000",t.innerHTML="NEAT"},G=t=>{const e=t.parentElement?.getElementsByTagName("a");if(e){for(let i=0;i<e.length;i++)if(e[i].id===F){N(e[i]);return}}const o=document.createElement("a");N(o),t.parentElement?.appendChild(o)};function U(){const t=new Date,e=t.getMinutes(),o=t.getSeconds();return e*60+o}function V(t=6){const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";let o="";for(let i=0;i<t;i++){const s=Math.floor(Math.random()*e.length);o+=e.charAt(s)}return o}function H(t,e){const o=document.createElement("a");o.download=e,o.href=t,document.body.appendChild(o),o.click(),document.body.removeChild(o)}u.NeatGradient=B,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
//# sourceMappingURL=index.umd.js.map