@bergetai/ui 0.3.5 → 0.4.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.cjs CHANGED
@@ -85,6 +85,7 @@ __export(index_exports, {
85
85
  DropdownMenuSubTrigger: () => DropdownMenuSubTrigger,
86
86
  DropdownMenuTrigger: () => DropdownMenuTrigger,
87
87
  EU_COUNTRY_CODES: () => EU_COUNTRY_CODES,
88
+ FOG_BRAND_PALETTE: () => FOG_BRAND_PALETTE,
88
89
  FeatureList: () => FeatureList,
89
90
  Field: () => Field,
90
91
  FieldContent: () => FieldContent,
@@ -96,6 +97,7 @@ __export(index_exports, {
96
97
  FieldSeparator: () => FieldSeparator,
97
98
  FieldSet: () => FieldSet,
98
99
  FieldTitle: () => FieldTitle,
100
+ FogIllustration: () => FogIllustration,
99
101
  Grid: () => Grid,
100
102
  HeroBlock: () => HeroBlock,
101
103
  Icon: () => Icon,
@@ -3694,6 +3696,324 @@ var WindowFrame = React43.forwardRef(
3694
3696
  }
3695
3697
  );
3696
3698
  WindowFrame.displayName = "WindowFrame";
3699
+
3700
+ // src/components/fog-illustration/FogIllustration.tsx
3701
+ var import_react4 = require("react");
3702
+ var import_jsx_runtime44 = require("react/jsx-runtime");
3703
+ var FOG_BRAND_PALETTE = {
3704
+ ink: "#171a1a",
3705
+ milk: "#f7f5ed",
3706
+ moss: "#598c6b"
3707
+ };
3708
+ var hexToRgb = (hex) => {
3709
+ let h = hex.replace("#", "");
3710
+ if (h.length === 3)
3711
+ h = h.split("").map((c) => c + c).join("");
3712
+ const n = Number.parseInt(h, 16);
3713
+ return [(n >> 16 & 255) / 255, (n >> 8 & 255) / 255, (n & 255) / 255];
3714
+ };
3715
+ var hexToRgbAll = (p) => ({
3716
+ ink: hexToRgb(p.ink),
3717
+ milk: hexToRgb(p.milk),
3718
+ moss: hexToRgb(p.moss)
3719
+ });
3720
+ var VERT = `#version 300 es
3721
+ void main() {
3722
+ vec2 p = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
3723
+ gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);
3724
+ }`;
3725
+ var SCENE_FRAG = `#version 300 es
3726
+ precision highp float;
3727
+ out vec4 outColor;
3728
+ uniform vec2 uRes;
3729
+ uniform float uTime;
3730
+ uniform sampler2D uNoise;
3731
+
3732
+ float noise(vec3 x) {
3733
+ // 3D value noise from the 2D random texture \u2014 iq's two-slice trick:
3734
+ // z slices are tiled into the u axis, two neighbours mixed by fract(z).
3735
+ vec3 p = floor(x), f = fract(x);
3736
+ f = f * f * (3.0 - 2.0 * f);
3737
+ vec2 uv = (p.xy + vec2(37.0, 239.0) * p.z) + f.xy;
3738
+ vec2 rg = texture(uNoise, (uv + 0.5) / 256.0).xy;
3739
+ return mix(rg.x, rg.y, f.z) * 2.0 - 1.0;
3740
+ }
3741
+
3742
+ float ground(vec3 pos, int oct) {
3743
+ float f = 0.0;
3744
+ float s = 1.4;
3745
+ vec3 p = pos * s * 0.1;
3746
+ for (int i = 0; i < 6; i++) {
3747
+ if (i >= oct) break;
3748
+ f += abs(noise(p)) * s;
3749
+ p = vec3(p.z * 5.0, p.xy * 3.0 + p.yx * 4.0 * vec2(1, -1)) * 2.0 / 5.0;
3750
+ s /= 2.0;
3751
+ }
3752
+ return (pos.y + f) * 0.8;
3753
+ }
3754
+
3755
+ float fogD(vec3 pos, int oct) {
3756
+ float f = 0.0;
3757
+ float s = 1.0;
3758
+ vec3 p = pos * 0.7;
3759
+ p += uTime * vec3(0.0, -0.02, 0.02);
3760
+ for (int i = 0; i < 6; i++) {
3761
+ if (i >= oct) break;
3762
+ f += noise(p) * s;
3763
+ p = vec3(p.z * 5.0, p.xy * 3.0 + p.yx * 4.0 * vec2(1, -1)) * 2.0 / 5.0;
3764
+ s /= 1.7;
3765
+ }
3766
+ f += smoothstep(0.2, 0.0, abs(pos.y + 1.0)) * 0.4;
3767
+ f += smoothstep(0.35, 0.15, abs(pos.y - 0.02)) * 0.7;
3768
+ f *= 1.0 - smoothstep(-0.1, 0.55, pos.y);
3769
+ f = smoothstep(0.45, 1.7, f);
3770
+ float g = ground(pos, 2);
3771
+ f *= 1.0 - g / (abs(g) + 0.04);
3772
+ return f;
3773
+ }
3774
+
3775
+ float airD(vec3 pos) { return exp2(-pos.y / 5.0 - 3.0); }
3776
+
3777
+ void main() {
3778
+ float time = uTime * 0.2;
3779
+ vec3 velocity = vec3(1.0, 0.0, 0.0);
3780
+ vec3 camPos = vec3(sin(time * 0.618) * 0.4, 0.62 + 0.08 * sin(time), 0.0) + time * velocity;
3781
+ vec3 camLook = vec3(-1.0, -0.3, 4.0) + (time - sin(time)) * velocity;
3782
+
3783
+ vec2 fc = gl_FragCoord.xy;
3784
+ vec3 ray = vec3((fc - uRes * 0.5) / uRes.x, 1.0);
3785
+ vec3 camDir = normalize(camLook - camPos);
3786
+ vec3 camRight = normalize(cross(vec3(0.0, 1.0, 0.0), camDir));
3787
+ vec3 camUp = cross(camDir, camRight);
3788
+ ray = normalize(ray.x * camRight + ray.y * camUp + ray.z * camDir);
3789
+
3790
+ vec3 sunDir = normalize(vec3(-3.0, 2.0, 1.0));
3791
+
3792
+ vec3 pos = camPos;
3793
+ float absorption = 1.0;
3794
+ float emission = 0.0;
3795
+ float fogFactor = 0.0;
3796
+ float lastStride = 0.0;
3797
+ float lastFog = 0.0;
3798
+ float lastAir = 0.0;
3799
+
3800
+ for (int i = 0; i < 80; i++) {
3801
+ float h = ground(pos, 4);
3802
+ float fog = fogD(pos, 3);
3803
+ float fogIntegral = lastStride * mix(fog, lastFog, 0.5);
3804
+ float air = airD(pos);
3805
+ float airIntegral = lastStride * mix(air, lastAir, 0.5);
3806
+
3807
+ float fogAbsDelta = pow(0.1, fogIntegral);
3808
+ float fogEmiDelta = 1.0 - fogAbsDelta;
3809
+ float shadowStep = 0.07;
3810
+ float shadow = (fog - fogD(pos + sunDir * shadowStep, 2)) / shadowStep;
3811
+ fogEmiDelta *= mix(0.2, 0.85, smoothstep(-1.0, 1.0, shadow));
3812
+
3813
+ float airAbsDelta = pow(0.55, airIntegral);
3814
+ float airEmiDelta = (1.0 - pow(0.55, airIntegral)) * 0.5;
3815
+
3816
+ float absDelta = fogAbsDelta * airAbsDelta;
3817
+ emission += absorption * sqrt(absDelta) * (fogEmiDelta + airEmiDelta);
3818
+ absorption *= absDelta;
3819
+
3820
+ fogFactor = max(fogFactor, (1.0 - absorption) * step(0.05, fog));
3821
+
3822
+ lastFog = fog;
3823
+ lastAir = air;
3824
+ h = min(h, 0.1);
3825
+ lastStride = h;
3826
+ pos += h * ray;
3827
+ if (h < 0.001) break;
3828
+ }
3829
+
3830
+ float brightness;
3831
+ if (absorption > 0.02) {
3832
+ // terrain visible \u2014 light it
3833
+ vec2 d = vec2(-1.0, 1.0) * 0.02;
3834
+ vec3 normal = normalize(
3835
+ ground(pos + d.xxx, 5) * d.xxx +
3836
+ ground(pos + d.xyy, 5) * d.xyy +
3837
+ ground(pos + d.yxy, 5) * d.yxy +
3838
+ ground(pos + d.yyx, 5) * d.yyx
3839
+ );
3840
+ float ao = smoothstep(-0.2, 1.5, ground(pos + normal * 0.3, 5) / 0.3);
3841
+ float shade = (0.5 * ao + 0.5 * max(dot(normal, sunDir), 0.0)) * 0.65;
3842
+ brightness = shade * absorption + emission;
3843
+ } else {
3844
+ brightness = emission;
3845
+ }
3846
+
3847
+ // Clear sky \u2014 rays that escape upward land on milk, whatever the
3848
+ // haze did. The poster look: light sky, dark ridges, fog between.
3849
+ float sky = smoothstep(-0.15, 0.35, ray.y) * 0.92;
3850
+ brightness = max(brightness, sky * absorption);
3851
+
3852
+ outColor = vec4(clamp(brightness, 0.0, 1.0), clamp(fogFactor, 0.0, 1.0), 0.0, 1.0);
3853
+ }`;
3854
+ var DITHER_FRAG = `#version 300 es
3855
+ precision highp float;
3856
+ out vec4 outColor;
3857
+ uniform vec2 uRes;
3858
+ uniform float uDot;
3859
+ uniform sampler2D uScene;
3860
+ uniform vec3 uInk;
3861
+ uniform vec3 uMilk;
3862
+ uniform vec3 uMoss;
3863
+
3864
+ float bayer2(vec2 a) { a = floor(a); return fract(a.x / 2.0 + a.y * a.y * 0.75); }
3865
+ float bayer4(vec2 a) { return bayer2(0.5 * a) * 0.25 + bayer2(a); }
3866
+ float hash12(vec2 p) {
3867
+ vec3 p3 = fract(vec3(p.xyx) * 0.1031);
3868
+ p3 += dot(p3, p3.yzx + 33.33);
3869
+ return fract((p3.x + p3.y) * p3.z);
3870
+ }
3871
+
3872
+ void main() {
3873
+ // Chunky cells: one dot decision per uDot\xD7uDot block \u2014 the dither
3874
+ // reads as visible pixels, not 1px noise.
3875
+ vec2 cell = floor(gl_FragCoord.xy / uDot);
3876
+ vec4 scene = texture(uScene, (cell * uDot + uDot * 0.5) / uRes);
3877
+ float darkness = 1.0 - scene.r;
3878
+ float jitter = (hash12(cell) - 0.5) * 0.3;
3879
+ float on = step(darkness, bayer4(cell) + jitter);
3880
+ vec3 col = scene.g > 0.5 ? uMoss : uInk;
3881
+ outColor = vec4(mix(col, uMilk, on), 1.0);
3882
+ }`;
3883
+ var compile = (gl, type, src) => {
3884
+ const sh = gl.createShader(type);
3885
+ if (!sh) throw new Error("shader creation failed");
3886
+ gl.shaderSource(sh, src);
3887
+ gl.compileShader(sh);
3888
+ if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
3889
+ throw new Error(gl.getShaderInfoLog(sh) || "shader compile failed");
3890
+ }
3891
+ return sh;
3892
+ };
3893
+ var program = (gl, frag) => {
3894
+ const p = gl.createProgram();
3895
+ if (!p) throw new Error("program creation failed");
3896
+ gl.attachShader(p, compile(gl, gl.VERTEX_SHADER, VERT));
3897
+ gl.attachShader(p, compile(gl, gl.FRAGMENT_SHADER, frag));
3898
+ gl.linkProgram(p);
3899
+ if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
3900
+ throw new Error(gl.getProgramInfoLog(p) || "program link failed");
3901
+ }
3902
+ return p;
3903
+ };
3904
+ var FogIllustration = ({ palette, speed = 1, className }) => {
3905
+ const ref = (0, import_react4.useRef)(null);
3906
+ const live = (0, import_react4.useRef)({ palette: { ...FOG_BRAND_PALETTE, ...palette }, speed });
3907
+ live.current = { palette: { ...FOG_BRAND_PALETTE, ...palette }, speed };
3908
+ (0, import_react4.useEffect)(() => {
3909
+ const canvas = ref.current;
3910
+ const parent = canvas?.parentElement;
3911
+ if (!canvas || !parent) return;
3912
+ const gl = canvas.getContext("webgl2", {
3913
+ antialias: false,
3914
+ alpha: false,
3915
+ preserveDrawingBuffer: true
3916
+ });
3917
+ if (!gl) return;
3918
+ let sceneProg;
3919
+ let ditherProg;
3920
+ try {
3921
+ sceneProg = program(gl, SCENE_FRAG);
3922
+ ditherProg = program(gl, DITHER_FRAG);
3923
+ } catch (err) {
3924
+ console.error("fog shader failed:", err);
3925
+ return;
3926
+ }
3927
+ const noiseTex = gl.createTexture();
3928
+ gl.bindTexture(gl.TEXTURE_2D, noiseTex);
3929
+ const N = 256;
3930
+ const data = new Uint8Array(N * N * 4);
3931
+ for (let i = 0; i < data.length; i += 4) {
3932
+ data[i] = Math.random() * 256;
3933
+ data[i + 1] = Math.random() * 256;
3934
+ data[i + 2] = Math.random() * 256;
3935
+ data[i + 3] = 255;
3936
+ }
3937
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, N, N, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
3938
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
3939
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
3940
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
3941
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
3942
+ const sceneTex = gl.createTexture();
3943
+ gl.bindTexture(gl.TEXTURE_2D, sceneTex);
3944
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
3945
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
3946
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
3947
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
3948
+ const fbo = gl.createFramebuffer();
3949
+ const SCALE = 0.3;
3950
+ const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3951
+ const start = performance.now();
3952
+ let raf = 0;
3953
+ let last = 0;
3954
+ const render = (elapsed) => {
3955
+ const w = parent.clientWidth;
3956
+ const h = parent.clientHeight;
3957
+ if (w === 0 || h === 0) return;
3958
+ const dpr = Math.min(window.devicePixelRatio || 1, 2);
3959
+ if (canvas.width !== Math.round(w * dpr) || canvas.height !== Math.round(h * dpr)) {
3960
+ canvas.width = Math.round(w * dpr);
3961
+ canvas.height = Math.round(h * dpr);
3962
+ }
3963
+ const sceneW = Math.max(64, Math.round(w * SCALE));
3964
+ const sceneH = Math.max(64, Math.round(h * SCALE));
3965
+ gl.bindTexture(gl.TEXTURE_2D, sceneTex);
3966
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sceneW, sceneH, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
3967
+ const t = elapsed * live.current.speed;
3968
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
3969
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, sceneTex, 0);
3970
+ gl.viewport(0, 0, sceneW, sceneH);
3971
+ gl.useProgram(sceneProg);
3972
+ gl.activeTexture(gl.TEXTURE0);
3973
+ gl.bindTexture(gl.TEXTURE_2D, noiseTex);
3974
+ gl.uniform1i(gl.getUniformLocation(sceneProg, "uNoise"), 0);
3975
+ gl.uniform2f(gl.getUniformLocation(sceneProg, "uRes"), sceneW, sceneH);
3976
+ gl.uniform1f(gl.getUniformLocation(sceneProg, "uTime"), t);
3977
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
3978
+ const { ink, milk, moss } = hexToRgbAll(live.current.palette);
3979
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
3980
+ gl.viewport(0, 0, canvas.width, canvas.height);
3981
+ gl.useProgram(ditherProg);
3982
+ gl.activeTexture(gl.TEXTURE0);
3983
+ gl.bindTexture(gl.TEXTURE_2D, sceneTex);
3984
+ gl.uniform1i(gl.getUniformLocation(ditherProg, "uScene"), 0);
3985
+ gl.uniform2f(gl.getUniformLocation(ditherProg, "uRes"), canvas.width, canvas.height);
3986
+ gl.uniform1f(gl.getUniformLocation(ditherProg, "uDot"), Math.max(3, Math.round(dpr * 2)));
3987
+ gl.uniform3f(gl.getUniformLocation(ditherProg, "uInk"), ...ink);
3988
+ gl.uniform3f(gl.getUniformLocation(ditherProg, "uMilk"), ...milk);
3989
+ gl.uniform3f(gl.getUniformLocation(ditherProg, "uMoss"), ...moss);
3990
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
3991
+ };
3992
+ render(0);
3993
+ if (!reduced) {
3994
+ const frame = (now) => {
3995
+ if (now - last >= 1e3 / 30) {
3996
+ last = now;
3997
+ render((now - start) / 1e3);
3998
+ }
3999
+ raf = requestAnimationFrame(frame);
4000
+ };
4001
+ raf = requestAnimationFrame(frame);
4002
+ }
4003
+ const observer = new ResizeObserver(() => render((performance.now() - start) / 1e3));
4004
+ observer.observe(parent);
4005
+ return () => {
4006
+ cancelAnimationFrame(raf);
4007
+ observer.disconnect();
4008
+ gl.deleteProgram(sceneProg);
4009
+ gl.deleteProgram(ditherProg);
4010
+ gl.deleteTexture(noiseTex);
4011
+ gl.deleteTexture(sceneTex);
4012
+ gl.deleteFramebuffer(fbo);
4013
+ };
4014
+ }, []);
4015
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("canvas", { ref, "aria-hidden": "true", className: cn("size-full", className) });
4016
+ };
3697
4017
  // Annotate the CommonJS export names for ESM import in node:
3698
4018
  0 && (module.exports = {
3699
4019
  Alert,
@@ -3751,6 +4071,7 @@ WindowFrame.displayName = "WindowFrame";
3751
4071
  DropdownMenuSubTrigger,
3752
4072
  DropdownMenuTrigger,
3753
4073
  EU_COUNTRY_CODES,
4074
+ FOG_BRAND_PALETTE,
3754
4075
  FeatureList,
3755
4076
  Field,
3756
4077
  FieldContent,
@@ -3762,6 +4083,7 @@ WindowFrame.displayName = "WindowFrame";
3762
4083
  FieldSeparator,
3763
4084
  FieldSet,
3764
4085
  FieldTitle,
4086
+ FogIllustration,
3765
4087
  Grid,
3766
4088
  HeroBlock,
3767
4089
  Icon,