@boyernick/standard-ui-react 0.4.2-canary.60 → 0.4.2-canary.61
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/package.json +1 -1
- package/src/carousel.tsx +1 -13
- package/src/glass.tsx +22 -41
- package/src/lib/lens-glass/config.ts +225 -0
- package/src/lib/lens-glass/renderer.ts +586 -0
- package/src/lib/lens-glass/shader.ts +138 -0
- package/src/lib/media-glass.ts +11 -13
- package/src/modal.tsx +2 -2
- package/src/lib/liquidglass/NOTICE.md +0 -24
- package/src/lib/liquidglass/index.d.ts +0 -45
- package/src/lib/liquidglass/index.js +0 -2862
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export const VERTEX_SHADER = `
|
|
2
|
+
attribute vec2 a_position;
|
|
3
|
+
varying vec2 v_uv;
|
|
4
|
+
void main() {
|
|
5
|
+
v_uv = a_position * 0.5 + 0.5;
|
|
6
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
7
|
+
}`;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* One pane, drawn into its own output rectangle. Coordinates are CSS pixels
|
|
11
|
+
* with y down: `u_origin` is the output's top-left in scene space, and the
|
|
12
|
+
* pane is centred on `u_center` with half-size `u_half`.
|
|
13
|
+
*/
|
|
14
|
+
export const FRAGMENT_SHADER = `
|
|
15
|
+
precision highp float;
|
|
16
|
+
varying vec2 v_uv;
|
|
17
|
+
|
|
18
|
+
uniform sampler2D u_scene;
|
|
19
|
+
uniform vec2 u_sceneSize;
|
|
20
|
+
uniform vec2 u_origin;
|
|
21
|
+
uniform vec2 u_outSize;
|
|
22
|
+
uniform vec2 u_center;
|
|
23
|
+
uniform vec2 u_half;
|
|
24
|
+
uniform float u_dpr;
|
|
25
|
+
|
|
26
|
+
uniform float u_radius;
|
|
27
|
+
uniform float u_power;
|
|
28
|
+
uniform float u_bezel;
|
|
29
|
+
uniform float u_bend;
|
|
30
|
+
uniform float u_dispersionRed;
|
|
31
|
+
uniform float u_dispersionBlue;
|
|
32
|
+
uniform float u_rim;
|
|
33
|
+
uniform float u_rimWidth;
|
|
34
|
+
uniform float u_specular;
|
|
35
|
+
uniform float u_frost;
|
|
36
|
+
uniform float u_grain;
|
|
37
|
+
uniform float u_dim;
|
|
38
|
+
uniform float u_fadeStart;
|
|
39
|
+
uniform float u_fadeEnd;
|
|
40
|
+
uniform float u_shadow;
|
|
41
|
+
uniform float u_hover;
|
|
42
|
+
uniform float u_press;
|
|
43
|
+
|
|
44
|
+
// A rounded rectangle whose corners are superellipses. Power 2 is a circular
|
|
45
|
+
// arc; around 4 is the continuous "squircle" corner.
|
|
46
|
+
float sdPane(vec2 p) {
|
|
47
|
+
float r = min(u_radius, min(u_half.x, u_half.y));
|
|
48
|
+
vec2 q = abs(p) - u_half + r;
|
|
49
|
+
vec2 m = max(q, 0.0);
|
|
50
|
+
float corner = u_power == 2.0
|
|
51
|
+
? length(m)
|
|
52
|
+
: pow(pow(m.x, u_power) + pow(m.y, u_power), 1.0 / u_power);
|
|
53
|
+
return corner + min(max(q.x, q.y), 0.0) - r;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
vec2 outwardNormal(vec2 p) {
|
|
57
|
+
float e = 0.5;
|
|
58
|
+
vec2 g = vec2(
|
|
59
|
+
sdPane(p + vec2(e, 0.0)) - sdPane(p - vec2(e, 0.0)),
|
|
60
|
+
sdPane(p + vec2(0.0, e)) - sdPane(p - vec2(0.0, e))
|
|
61
|
+
);
|
|
62
|
+
float l = length(g);
|
|
63
|
+
return l > 1e-5 ? g / l : vec2(0.0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
vec3 ground(vec2 scenePx) {
|
|
67
|
+
vec2 uv = clamp(scenePx / u_sceneSize, vec2(0.0), vec2(1.0));
|
|
68
|
+
return texture2D(u_scene, uv).rgb;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Frost: 16 taps on a golden-angle spiral out to about two sigma.
|
|
72
|
+
vec3 frosted(vec2 scenePx) {
|
|
73
|
+
if (u_frost < 0.05) return ground(scenePx);
|
|
74
|
+
vec3 sum = vec3(0.0);
|
|
75
|
+
float weights = 0.0;
|
|
76
|
+
for (int i = 0; i < 16; i++) {
|
|
77
|
+
float fi = float(i);
|
|
78
|
+
float r = sqrt((fi + 0.5) / 16.0) * 2.0 * u_frost;
|
|
79
|
+
float a = fi * 2.39996323;
|
|
80
|
+
float w = exp(-(r * r) / (2.0 * u_frost * u_frost));
|
|
81
|
+
sum += ground(scenePx + vec2(cos(a), sin(a)) * r) * w;
|
|
82
|
+
weights += w;
|
|
83
|
+
}
|
|
84
|
+
return sum / weights;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
float hash(vec2 p) {
|
|
88
|
+
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
void main() {
|
|
92
|
+
vec2 scenePx = u_origin + vec2(v_uv.x, 1.0 - v_uv.y) * u_outSize;
|
|
93
|
+
vec2 p = scenePx - u_center;
|
|
94
|
+
float d = sdPane(p);
|
|
95
|
+
|
|
96
|
+
// Outside: only a soft contact shadow, heavier below the pane.
|
|
97
|
+
if (d > 0.0) {
|
|
98
|
+
float below = smoothstep(-0.6, 0.8, p.y / max(u_half.y, 1.0));
|
|
99
|
+
float shadow = u_shadow * (1.0 - 0.35 * u_press) * exp(-(d * d) / 40.0) * below;
|
|
100
|
+
gl_FragColor = vec4(0.0, 0.0, 0.0, shadow);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
float inside = -d;
|
|
105
|
+
vec2 n = outwardNormal(p);
|
|
106
|
+
|
|
107
|
+
// The bezel bends the ground outward across its width: the pane shows what
|
|
108
|
+
// lies just past its edge, compressed into the band, as a thick lens does.
|
|
109
|
+
float t = u_bezel > 0.0 ? clamp(1.0 - inside / u_bezel, 0.0, 1.0) : 0.0;
|
|
110
|
+
float profile = t * t * (3.0 - 2.0 * t);
|
|
111
|
+
vec2 offset = n * u_bend * (1.0 - 0.35 * u_press) * profile;
|
|
112
|
+
|
|
113
|
+
vec3 color = vec3(
|
|
114
|
+
frosted(scenePx + offset * u_dispersionRed).r,
|
|
115
|
+
frosted(scenePx + offset).g,
|
|
116
|
+
frosted(scenePx + offset * u_dispersionBlue).b
|
|
117
|
+
);
|
|
118
|
+
color *= u_dim + 0.06 * u_hover;
|
|
119
|
+
|
|
120
|
+
// Rim light, strongest where the edge faces the light (top left), and a
|
|
121
|
+
// sheen across the lit side of the bezel.
|
|
122
|
+
vec2 light = normalize(vec2(-0.55, -1.0));
|
|
123
|
+
float facing = max(dot(n, light), 0.0);
|
|
124
|
+
float rim = 1.0 - smoothstep(0.0, u_rimWidth, inside);
|
|
125
|
+
color += u_rim * (1.0 + 0.4 * u_hover) * rim * (0.55 + 0.45 * facing);
|
|
126
|
+
color += u_specular * 0.35 * pow(t, 3.0) * facing;
|
|
127
|
+
|
|
128
|
+
// Grain, fixed to the device pixel grid so a still pane never needs redrawing.
|
|
129
|
+
color += (hash(floor(scenePx * u_dpr)) - 0.5) * u_grain;
|
|
130
|
+
|
|
131
|
+
// Optional fade down the pane.
|
|
132
|
+
float yFrac = (p.y + u_half.y) / (2.0 * u_half.y);
|
|
133
|
+
float fade = u_fadeEnd > u_fadeStart ? 1.0 - smoothstep(u_fadeStart, u_fadeEnd, yFrac) : 1.0;
|
|
134
|
+
color = mix(ground(scenePx), color, fade);
|
|
135
|
+
|
|
136
|
+
float coverage = clamp(inside * u_dpr + 0.5, 0.0, 1.0);
|
|
137
|
+
gl_FragColor = vec4(clamp(color, 0.0, 1.0), coverage);
|
|
138
|
+
}`;
|
package/src/lib/media-glass.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
shadowSpread: 12,
|
|
13
|
-
shadowOffsetY: 3,
|
|
1
|
+
import type { GlassConfig } from "./lens-glass/config";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared material for controls over images and video. Their icons are white
|
|
5
|
+
* (`text-fg-scrim`), so the ground is dimmed further than the default to keep
|
|
6
|
+
* them legible over a bright frame, and frosted a little more.
|
|
7
|
+
*/
|
|
8
|
+
export const mediaGlass: GlassConfig = {
|
|
9
|
+
dim: 0.62,
|
|
10
|
+
frost: 4,
|
|
11
|
+
shadow: 0.2,
|
|
14
12
|
}
|
package/src/modal.tsx
CHANGED
|
@@ -326,7 +326,7 @@ export const ModalContent = ({
|
|
|
326
326
|
{...props}
|
|
327
327
|
>
|
|
328
328
|
<TooltipProvider delay={250}>
|
|
329
|
-
<GlassRoot interactiveLighting defaults={mediaGlass} className="size-full">
|
|
329
|
+
<GlassRoot interactiveLighting defaults={mediaGlass} className="size-full [--glass-ground:var(--color-surface-scrim)]">
|
|
330
330
|
<ModalBackground src={src} />
|
|
331
331
|
<DialogTitle className="sr-only">{alt}</DialogTitle>
|
|
332
332
|
<div
|
|
@@ -499,7 +499,7 @@ const GalleryContent = ({
|
|
|
499
499
|
)}
|
|
500
500
|
>
|
|
501
501
|
<TooltipProvider delay={250}>
|
|
502
|
-
<GlassRoot interactiveLighting defaults={mediaGlass} className="size-full">
|
|
502
|
+
<GlassRoot interactiveLighting defaults={mediaGlass} className="size-full [--glass-ground:var(--color-surface-scrim)]">
|
|
503
503
|
<ModalBackground src={activeImage.src} />
|
|
504
504
|
<DialogTitle className="sr-only">{activeImage.alt}</DialogTitle>
|
|
505
505
|
<p className="sr-only" aria-live="polite">
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# LiquidGlass
|
|
2
|
-
|
|
3
|
-
Vendored from `@ybouane/liquidglass@1.0.3`.
|
|
4
|
-
|
|
5
|
-
Source: https://github.com/ybouane/liquidglass
|
|
6
|
-
License: MIT (as declared by the upstream package).
|
|
7
|
-
|
|
8
|
-
`index.js` is the package's published bundled WebGL renderer. StandardUI
|
|
9
|
-
vendors the build because version 1.0.3 publishes a `postinstall`
|
|
10
|
-
command whose `patch-package` executable is not a runtime dependency.
|
|
11
|
-
|
|
12
|
-
Local patch: `LiquidGlass.init()` destroys a partially initialized instance
|
|
13
|
-
before rethrowing a startup error, releasing its canvas, listeners and WebGL
|
|
14
|
-
resources.
|
|
15
|
-
|
|
16
|
-
StandardUI's `data-glass-radius="css"` panes derive the shader radius from the
|
|
17
|
-
computed CSS radius. Disabled buttons suppress shader hover/press feedback.
|
|
18
|
-
|
|
19
|
-
Responsive images are decoded from `currentSrc` without `srcset` before canvas
|
|
20
|
-
sampling. This keeps object-fit crop coordinates in resource pixels instead of
|
|
21
|
-
mixing density-corrected `naturalWidth` with full-resolution canvas coordinates.
|
|
22
|
-
|
|
23
|
-
Injected canvases compensate for the host's border so the rendered lens stays
|
|
24
|
-
centered on bordered controls and their icons.
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type surface for the vendored @ybouane/liquidglass 1.0.3 renderer.
|
|
3
|
-
* Source: https://github.com/ybouane/liquidglass
|
|
4
|
-
* License: MIT
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export interface GlassConfig {
|
|
8
|
-
blurAmount: number;
|
|
9
|
-
refraction: number;
|
|
10
|
-
chromAberration: number;
|
|
11
|
-
edgeHighlight: number;
|
|
12
|
-
specular: number;
|
|
13
|
-
fresnel: number;
|
|
14
|
-
distortion: number;
|
|
15
|
-
cornerRadius: number;
|
|
16
|
-
zRadius: number;
|
|
17
|
-
opacity: number;
|
|
18
|
-
saturation: number;
|
|
19
|
-
tintStrength: number;
|
|
20
|
-
brightness: number;
|
|
21
|
-
shadowOpacity: number;
|
|
22
|
-
shadowSpread: number;
|
|
23
|
-
shadowOffsetY: number;
|
|
24
|
-
floating: boolean;
|
|
25
|
-
button: boolean;
|
|
26
|
-
bevelMode: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface LiquidGlassOptions {
|
|
30
|
-
root: HTMLElement;
|
|
31
|
-
glassElements?: NodeListOf<HTMLElement> | HTMLElement[];
|
|
32
|
-
defaults?: Partial<GlassConfig>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export declare class LiquidGlass {
|
|
36
|
-
static init(options: LiquidGlassOptions): Promise<LiquidGlass>;
|
|
37
|
-
readonly root: HTMLElement;
|
|
38
|
-
readonly defaults: GlassConfig;
|
|
39
|
-
fps: number;
|
|
40
|
-
destroy(): void;
|
|
41
|
-
markChanged(element?: HTMLElement): void;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export declare const DEFAULTS: GlassConfig;
|
|
45
|
-
export declare function invalidateFontEmbedCache(): void;
|