vireglass 1.0.0 → 2.1.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/README.md +83 -9
- package/dist/adapters-BfeAopGO.d.ts +154 -0
- package/dist/adapters-DugC6Qri.d.cts +154 -0
- package/dist/chunk-3PGYF2NK.js +360 -0
- package/dist/chunk-3PGYF2NK.js.map +1 -0
- package/dist/chunk-BZC2WHCK.js +377 -0
- package/dist/chunk-BZC2WHCK.js.map +1 -0
- package/dist/{chunk-HF2AWZEZ.js → chunk-FL5UZPY5.js} +208 -606
- package/dist/chunk-FL5UZPY5.js.map +1 -0
- package/dist/chunk-P2ZOODXD.js +58 -0
- package/dist/chunk-P2ZOODXD.js.map +1 -0
- package/dist/chunk-TTOKBARR.js +456 -0
- package/dist/chunk-TTOKBARR.js.map +1 -0
- package/dist/dom.cjs +2054 -0
- package/dist/dom.cjs.map +1 -0
- package/dist/dom.d.cts +358 -0
- package/dist/dom.d.ts +358 -0
- package/dist/dom.js +1083 -0
- package/dist/dom.js.map +1 -0
- package/dist/geometry-GvXtt-_S.d.ts +105 -0
- package/dist/geometry-RhKd7CM5.d.cts +105 -0
- package/dist/group-model-DwtixGhG.d.cts +203 -0
- package/dist/group-model-z4N27qsC.d.ts +203 -0
- package/dist/index.cjs +735 -244
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -113
- package/dist/index.d.ts +122 -113
- package/dist/index.js +6 -277
- package/dist/index.js.map +1 -1
- package/dist/law.cjs +478 -0
- package/dist/law.cjs.map +1 -0
- package/dist/law.d.cts +543 -0
- package/dist/law.d.ts +543 -0
- package/dist/law.js +3 -0
- package/dist/law.js.map +1 -0
- package/dist/{material-CkUHUBoy.d.cts → material-CnUmdKg1.d.cts} +1 -1
- package/dist/{material-CkUHUBoy.d.ts → material-CnUmdKg1.d.ts} +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/reference.cjs +221 -0
- package/dist/reference.cjs.map +1 -0
- package/dist/reference.d.cts +183 -0
- package/dist/reference.d.ts +183 -0
- package/dist/reference.js +197 -0
- package/dist/reference.js.map +1 -0
- package/dist/web/index.cjs +247 -165
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.d.cts +4 -29
- package/dist/web/index.d.ts +4 -29
- package/dist/web/index.js +5 -90
- package/dist/web/index.js.map +1 -1
- package/docs/adr-001-rendering.md +288 -0
- package/docs/architecture.md +161 -0
- package/docs/benchmarks.md +191 -0
- package/docs/dom.md +160 -0
- package/docs/law.md +65 -0
- package/docs/material-lab.md +799 -0
- package/docs/platform-parity.md +266 -0
- package/docs/reference.md +397 -0
- package/package.json +24 -3
- package/src/accent.ts +35 -0
- package/src/accessibility.ts +30 -16
- package/src/adapters.ts +71 -3
- package/src/appear.ts +45 -0
- package/src/concentric.ts +66 -0
- package/src/dom/body.ts +98 -0
- package/src/dom/displacement.ts +168 -0
- package/src/dom/group.ts +124 -0
- package/src/dom/index.ts +747 -0
- package/src/dom/map-cache.ts +37 -0
- package/src/dom/nesting.ts +32 -0
- package/src/dom/preferences.ts +53 -0
- package/src/dom/probe.ts +163 -0
- package/src/dom/rim.ts +103 -0
- package/src/dom/scroll-edge.ts +106 -0
- package/src/dom/shadow.ts +56 -0
- package/src/dom/spectral-map.ts +102 -0
- package/src/dom/support.ts +47 -0
- package/src/geometry.ts +41 -14
- package/src/glass-scale.ts +3 -5
- package/src/index.ts +3 -1
- package/src/law.ts +562 -0
- package/src/lens-shader.ts +53 -30
- package/src/native/glass-surface.tsx +8 -14
- package/src/native/provider.tsx +22 -2
- package/src/optics.ts +43 -62
- package/src/reference.ts +9 -0
- package/src/scroll-edge.ts +22 -7
- package/src/sdf.ts +203 -8
- package/src/shadow-tint.ts +23 -0
- package/src/spectral.ts +110 -0
- package/src/surface-shader.ts +8 -6
- package/src/touch-response.ts +42 -27
- package/src/web/index.ts +0 -1
- package/dist/adapters-BPB0D5nr.d.cts +0 -357
- package/dist/adapters-BgSc-smX.d.ts +0 -357
- package/dist/chunk-HF2AWZEZ.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
A liquid glass material for interfaces, derived from optics rather than assembled from effects.
|
|
4
4
|
|
|
5
|
-
One material model,
|
|
6
|
-
|
|
5
|
+
One material model, three render targets: **WebGL2** and **live DOM** in the browser, **AGSL** on
|
|
6
|
+
Android. The DOM target refracts the page itself — real elements, real text, no canvas — so glass
|
|
7
|
+
can go over content a renderer never drew. Apache-2.0.
|
|
7
8
|
|
|
8
9
|
```bash
|
|
9
10
|
npm install vireglass
|
|
@@ -83,10 +84,72 @@ renderer.render({
|
|
|
83
84
|
`render` also returns one backdrop probe per element — mean lightness, 10th/90th percentiles
|
|
84
85
|
and variegation of what lies under it. That is what the adaptation layer reads.
|
|
85
86
|
|
|
86
|
-
> **WebGL does not see the DOM
|
|
87
|
-
>
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
> **WebGL does not see the DOM**, so this renderer refracts only what it drew itself — hence the
|
|
88
|
+
> `scene` callback. For glass over your actual page, use `vireglass/dom` below.
|
|
89
|
+
|
|
90
|
+
## Live DOM
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { attachGlass } from 'vireglass/dom';
|
|
94
|
+
|
|
95
|
+
const glass = attachGlass(document.querySelector('.player'), {
|
|
96
|
+
material: MATERIAL_PRESETS.glass,
|
|
97
|
+
});
|
|
98
|
+
// glass.update() after a scroll or a theme change, glass.destroy() on unmount
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The element now refracts the real page behind it. No canvas, no duplicate render of your UI.
|
|
102
|
+
|
|
103
|
+
It works by handing `backdrop-filter` an SVG filter whose `feDisplacementMap` bends the backdrop
|
|
104
|
+
along a map derived from the same material model the other renderers use. The browser never gives
|
|
105
|
+
the page's pixels to script — that boundary is what stops a page reading your cross-origin frames
|
|
106
|
+
and visited links — so the displacement happens inside the compositor, where the pixels already are.
|
|
107
|
+
|
|
108
|
+
It carries the material, not a corner of it: refraction with per-channel dispersion, the rim with
|
|
109
|
+
its two opposing arcs and dark edge, the adaptive shadow, the body under legibility and presence,
|
|
110
|
+
and the finger response — press, drag, the release wave and the rise into glass.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
glass.setMorph({ smoothing: 34, shape: { offsetX: 150, offsetY: -78, width: 170, height: 92, cornerRadius: 28 } });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Two shapes joined through the smooth union — §5's merging and splitting. What the shapes mean is
|
|
117
|
+
your choreography; the material only knows how two silhouettes join.
|
|
118
|
+
|
|
119
|
+
`attachGlass` writes CSS custom properties you can use directly:
|
|
120
|
+
|
|
121
|
+
| | |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `--vireglass-ink-color` | ink colour for this backdrop, already resolved |
|
|
124
|
+
| `--vireglass-body-color` | the glass body: density from the model, hue from the surroundings |
|
|
125
|
+
| `--vireglass-tint-color` | ambient colour alone |
|
|
126
|
+
| `--vireglass-rim`, `--vireglass-rim-width` | the hairline's gradient, applied for you |
|
|
127
|
+
| `--vireglass-shadow` | the adaptive shadow, also written to `box-shadow` unless you opt out |
|
|
128
|
+
| `--vireglass-radius`, `--vireglass-radius-min` | for concentric children (§11) |
|
|
129
|
+
| `--vireglass-ink`, `--vireglass-tint`, `--vireglass-body-density` | the model's raw numbers |
|
|
130
|
+
|
|
131
|
+
The three system accessibility settings are read from the browser's own media queries and
|
|
132
|
+
followed while the page is open — reduced transparency frosts the glass, increased contrast takes
|
|
133
|
+
the element by its silhouette, reduced motion holds it still. A system setting outranks the
|
|
134
|
+
material preset and the user's own clarity slider (`scale`), because the user needs contrast more
|
|
135
|
+
than they need the look.
|
|
136
|
+
|
|
137
|
+
Three things to know before you reach for it:
|
|
138
|
+
|
|
139
|
+
- **It renders the whole material.** Refraction with per-channel dispersion, the rim with its two
|
|
140
|
+
opposing arcs and dark edge, the adaptive shadow, the body under legibility and presence, the
|
|
141
|
+
finger response, and the spectral edge — diffraction and interference baked into a hue map and
|
|
142
|
+
multiplied in, since a filter graph cannot evaluate a function per pixel but can multiply by an
|
|
143
|
+
image.
|
|
144
|
+
|
|
145
|
+
- **The refraction is Chromium-only today.** Firefox does not support a filter reference in
|
|
146
|
+
`backdrop-filter` and has closed the request as not planned; Safari does not yet, though WebKit
|
|
147
|
+
has patches in flight. Elsewhere `attachGlass` falls back to blur, saturation and tint from the
|
|
148
|
+
same optics — detected by measurement, never by user-agent string.
|
|
149
|
+
- **There is no pixel probe, so adaptation reads declared styles.** The grid under the element is
|
|
150
|
+
sampled through `elementsFromPoint` and the background stack is composited. That is exact for
|
|
151
|
+
colour-defined surfaces and blind to images, video and canvas — pass your own `sample` there,
|
|
152
|
+
since your app already knows its cover-art accent.
|
|
90
153
|
|
|
91
154
|
## Android / React Native
|
|
92
155
|
|
|
@@ -157,9 +220,13 @@ preference; `applyGlassScale` gives that preference its own axis, ultra clear to
|
|
|
157
220
|
|
|
158
221
|
```bash
|
|
159
222
|
npm run typecheck
|
|
160
|
-
npm test
|
|
161
|
-
npm run check:glsl
|
|
223
|
+
npm test
|
|
224
|
+
npm run check:glsl # both shaders compile and link as GLSL ES 3.0
|
|
162
225
|
npm run check:optics
|
|
226
|
+
npm run check:law # every calibrated number is in src/law.ts, cited or named unmeasured
|
|
227
|
+
npm run check:dom # a real browser: the glass bends live DOM, and only where it should
|
|
228
|
+
npm run check:package # packs, installs into an empty project, loads every entry point
|
|
229
|
+
npm run check:readme # every name the documentation tells you to import exists
|
|
163
230
|
```
|
|
164
231
|
|
|
165
232
|
`check:optics` is the interesting one. It renders the material over a sweep of backdrops and
|
|
@@ -171,7 +238,9 @@ canvas, and that the rim gathers what is behind it.
|
|
|
171
238
|
|
|
172
239
|
## Limits — read these before adopting
|
|
173
240
|
|
|
174
|
-
- **
|
|
241
|
+
- **Glass over live DOM refracts in Chromium only**, and falls back to blur elsewhere. Its
|
|
242
|
+
adaptation reads declared styles rather than pixels, so images and video need a supplied
|
|
243
|
+
`sample`. See *Live DOM* above.
|
|
175
244
|
- **Refraction needs Android 13+** (`RenderEffect`). Below that it degrades to an affine
|
|
176
245
|
magnifier: a loupe, not a lens.
|
|
177
246
|
- **No iOS.** There is no public API for reading what is behind a view.
|
|
@@ -200,6 +269,8 @@ canvas, and that the rim gathers what is behind it.
|
|
|
200
269
|
| `docs/adr-001-rendering.md` | the rendering architecture decision and its evidence |
|
|
201
270
|
| `docs/platform-parity.md` | how web and Android are kept numerically in agreement |
|
|
202
271
|
| `docs/benchmarks.md` | measurement protocol, device, numbers |
|
|
272
|
+
| `docs/dom.md` | the DOM renderer: the technique, what it renders, what it costs |
|
|
273
|
+
| `docs/law.md` | where every calibrated number lives, and which ones nobody has measured |
|
|
203
274
|
| `docs/material-lab.md` | selected entries from the experiment journal |
|
|
204
275
|
|
|
205
276
|
## Calibration
|
|
@@ -209,6 +280,9 @@ sessions 219 and 356 and related design talks — and the documentation cites th
|
|
|
209
280
|
timestamp so the claims can be checked. No Apple code, assets or footage is included in or
|
|
210
281
|
distributed with this package.
|
|
211
282
|
|
|
283
|
+
Every calibrated number lives in `src/law.ts` with its provenance, and `check:law` names the ones
|
|
284
|
+
that have none: **42 of 120** today. See [`docs/law.md`](docs/law.md).
|
|
285
|
+
|
|
212
286
|
## License
|
|
213
287
|
|
|
214
288
|
Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { V as VireGlassGeometry } from './geometry-GvXtt-_S.js';
|
|
2
|
+
import { V as VireGlassOptics, o as VireGlassDebugMode } from './material-CnUmdKg1.js';
|
|
3
|
+
|
|
4
|
+
/** Smooth union with a second shape — bench morphing experiment only. */
|
|
5
|
+
type VireGlassMorph = {
|
|
6
|
+
offsetX: number;
|
|
7
|
+
offsetY: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
cornerRadius: number;
|
|
11
|
+
/** Seam smoothing radius in dp; 0 turns the second shape off. */
|
|
12
|
+
smoothing: number;
|
|
13
|
+
};
|
|
14
|
+
/** Surface response to a finger: the field around the touch point deforms, not the shape's
|
|
15
|
+
* bounding box (`vgTouchWarp` in `sdf.ts`). Lengths in dp; `radius` = 0 turns the response off
|
|
16
|
+
* entirely. */
|
|
17
|
+
type VireGlassTouch = {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
pullX: number;
|
|
21
|
+
pullY: number;
|
|
22
|
+
press: number;
|
|
23
|
+
radius: number;
|
|
24
|
+
waveAmp: number;
|
|
25
|
+
wavePhase: number;
|
|
26
|
+
};
|
|
27
|
+
/** Tinted glass for the primary action (M 16:08). Color is RGB 0…1. */
|
|
28
|
+
type VireGlassAccent = {
|
|
29
|
+
color: readonly [number, number, number];
|
|
30
|
+
amount?: number;
|
|
31
|
+
};
|
|
32
|
+
/** Default tint fraction: the color reads, but content beneath it is still visible. */
|
|
33
|
+
declare const ACCENT_AMOUNT: 0.8;
|
|
34
|
+
/** Magnification at the flat center. Kept separate from the uniform channel: it's also used by
|
|
35
|
+
* the fallback below Android 13, where there's no RuntimeShader and only an affine magnifier is
|
|
36
|
+
* left. */
|
|
37
|
+
declare const lensMagnify: (o: VireGlassOptics) => number;
|
|
38
|
+
/** Props for the native view. Besides the uniform channel, only what the view uses itself lives
|
|
39
|
+
* here: the shader source and the visible glass's size (the probe rectangle is taken from it). */
|
|
40
|
+
declare function toLensProps(optics: VireGlassOptics, geometry: VireGlassGeometry, density: number, options?: {
|
|
41
|
+
debug?: VireGlassDebugMode;
|
|
42
|
+
morph?: VireGlassMorph;
|
|
43
|
+
/** Third shape of the fused body; a zero size turns it off. */
|
|
44
|
+
morph2?: VireGlassMorph;
|
|
45
|
+
groupProbe?: number[];
|
|
46
|
+
touch?: VireGlassTouch;
|
|
47
|
+
/** Progress fraction, 0…1: to the left of the boundary the element is active. `undefined` means no progress. */
|
|
48
|
+
progress?: number;
|
|
49
|
+
/** Key light direction in screen space; defaults to the light at rest. */
|
|
50
|
+
light?: readonly [number, number];
|
|
51
|
+
/** 0…1: the lens builds up as the element appears — instead of a plain fade. */
|
|
52
|
+
appear?: number;
|
|
53
|
+
/** Tint for the primary action: the glass color and the fraction it lays over the content. */
|
|
54
|
+
accent?: VireGlassAccent;
|
|
55
|
+
}): {
|
|
56
|
+
uniformNames: string[];
|
|
57
|
+
uniformSizes: number[];
|
|
58
|
+
uniformValues: number[];
|
|
59
|
+
shaderSource: string;
|
|
60
|
+
glassWidth: number;
|
|
61
|
+
glassHeight: number;
|
|
62
|
+
};
|
|
63
|
+
/** Static part of the surface uniforms. Dynamics (gesture, press, light) get mixed in inside the
|
|
64
|
+
* component's worklet — the adapter must stay an ordinary function. */
|
|
65
|
+
declare function toSurfaceUniforms(optics: VireGlassOptics, geometry: VireGlassGeometry, options?: {
|
|
66
|
+
debug?: VireGlassDebugMode;
|
|
67
|
+
morph?: VireGlassMorph;
|
|
68
|
+
/** Third shape of the fused body; a zero size turns it off. */
|
|
69
|
+
morph2?: VireGlassMorph;
|
|
70
|
+
dragLimit?: number;
|
|
71
|
+
shadow?: number;
|
|
72
|
+
/** Average ambient color around the element: light from it bleeds into the shadow (reference 219 @8:22). */
|
|
73
|
+
ambient?: readonly [number, number, number];
|
|
74
|
+
/** The lens draws the glass body — the surface is left with the highlight, shadow and icon. */
|
|
75
|
+
bodyInLens?: boolean;
|
|
76
|
+
touch?: VireGlassTouch;
|
|
77
|
+
/** Progress fraction, 0…1: to the left of the boundary the element is active. `undefined` means no progress. */
|
|
78
|
+
progress?: number;
|
|
79
|
+
/** 0…1: the element is appearing — shadow and ink build up together with the lens. */
|
|
80
|
+
appear?: number;
|
|
81
|
+
/** 0 — the element sinks in under the finger, 1 — it rises into glass (reference §5). */
|
|
82
|
+
lift?: number;
|
|
83
|
+
}): {
|
|
84
|
+
u_center: number[];
|
|
85
|
+
u_halfSize: number[];
|
|
86
|
+
u_corner: number;
|
|
87
|
+
u_bevel: number;
|
|
88
|
+
u_thickness: number;
|
|
89
|
+
u_morphOffset: number[];
|
|
90
|
+
u_morphHalf: number[];
|
|
91
|
+
u_morphCorner: number;
|
|
92
|
+
u_morphK: number;
|
|
93
|
+
u_morph2Offset: number[];
|
|
94
|
+
u_morph2Half: number[];
|
|
95
|
+
u_morph2Corner: number;
|
|
96
|
+
u_edgeDensity: number;
|
|
97
|
+
u_dispersion: number;
|
|
98
|
+
u_refraction: number;
|
|
99
|
+
u_tint: number[];
|
|
100
|
+
u_shadow: number;
|
|
101
|
+
u_ambient: readonly [number, number, number];
|
|
102
|
+
u_shadowReach: number;
|
|
103
|
+
u_touch: number[];
|
|
104
|
+
u_pull: number[];
|
|
105
|
+
u_touchPress: number;
|
|
106
|
+
u_touchRadius: number;
|
|
107
|
+
u_wave: number[];
|
|
108
|
+
u_presence: number;
|
|
109
|
+
u_progress: number;
|
|
110
|
+
u_appear: number;
|
|
111
|
+
u_lift: number;
|
|
112
|
+
u_debug: number;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Surface fields that are LENGTHS: the adapter's contract is specified in dp, and on the web each
|
|
116
|
+
* one of them has to be multiplied by screen density. The list lives here rather than in the
|
|
117
|
+
* renderer, where it used to be a dozen and a half manual multiplications in a row: a missed
|
|
118
|
+
* field there was only caught by eye, and the miss isn't visible everywhere — at density 1,
|
|
119
|
+
* multiplying is indistinguishable from not doing it.
|
|
120
|
+
*/
|
|
121
|
+
type SurfaceUniforms = ReturnType<typeof toSurfaceUniforms>;
|
|
122
|
+
declare const SURFACE_LENGTH_UNIFORMS: readonly ["u_halfSize", "u_corner", "u_bevel", "u_morphOffset", "u_morphHalf", "u_morphCorner", "u_morphK", "u_morph2Offset", "u_morph2Half", "u_morph2Corner", "u_shadowReach", "u_touch", "u_pull", "u_touchRadius"];
|
|
123
|
+
/**
|
|
124
|
+
* Surface uniforms in device pixels. Android draws in dp and calls the adapter as-is; the web
|
|
125
|
+
* needs this conversion. `u_center` isn't part of it: the renderer knows the element's center on
|
|
126
|
+
* its own.
|
|
127
|
+
*/
|
|
128
|
+
declare function toDeviceSurfaceUniforms(raw: SurfaceUniforms, density: number): SurfaceUniforms;
|
|
129
|
+
/** Key light direction in screen coordinates, for when the orientation response is off. */
|
|
130
|
+
declare const REST_LIGHT: readonly [number, number];
|
|
131
|
+
/** Uniforms the component mixes in inside the worklet (press, active, light direction) and via
|
|
132
|
+
* the icon layer. Listed here so a test can check the shader contract's completeness without
|
|
133
|
+
* importing the component itself (it pulls in Skia and doesn't come up in a node environment). */
|
|
134
|
+
declare const DYNAMIC_UNIFORMS: readonly ["u_press", "u_active"];
|
|
135
|
+
declare const ICON_UNIFORMS: readonly ["u_iconOn", "u_iconScale", "u_inkIdle", "u_inkActive"];
|
|
136
|
+
/** App-colored overlay layer on the glass. The `u_overlay` sampler shares its contract with the
|
|
137
|
+
* ink mask and is sampled at the SAME coordinate — otherwise deformation would carry them apart. */
|
|
138
|
+
declare const OVERLAY_UNIFORMS: readonly ["u_overlayOn"];
|
|
139
|
+
declare function morphBetween(a: VireGlassGeometry, b: VireGlassGeometry, offsetX: number, offsetY: number, t: number): VireGlassMorph | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* MITOSIS: the second shape grows OUT OF the first and travels to its place, instead of appearing
|
|
142
|
+
* beside it at full size. A menu coming out of its button, a control dividing into segments.
|
|
143
|
+
*
|
|
144
|
+
* `morphBetween` is the other half — two shapes that are both already where they belong, fusing
|
|
145
|
+
* into one body — and run backwards it is meiosis, the neck thinning until it breaks. What neither
|
|
146
|
+
* of them may do is pop: at any `t` above zero this returns one continuous body, because that is
|
|
147
|
+
* the whole of what the reference says a material transition is.
|
|
148
|
+
*
|
|
149
|
+
* The choreography stays the host's: what the shapes MEAN is the app's business. How a silhouette
|
|
150
|
+
* emerges from another silhouette is the material's, the same way the spring under a finger is.
|
|
151
|
+
*/
|
|
152
|
+
declare function morphOutOf(source: VireGlassGeometry, target: VireGlassGeometry, offsetX: number, offsetY: number, t: number): VireGlassMorph | undefined;
|
|
153
|
+
|
|
154
|
+
export { ACCENT_AMOUNT as A, DYNAMIC_UNIFORMS as D, ICON_UNIFORMS as I, OVERLAY_UNIFORMS as O, REST_LIGHT as R, SURFACE_LENGTH_UNIFORMS as S, type VireGlassAccent as V, type SurfaceUniforms as a, type VireGlassMorph as b, type VireGlassTouch as c, morphOutOf as d, toLensProps as e, toSurfaceUniforms as f, lensMagnify as l, morphBetween as m, toDeviceSurfaceUniforms as t };
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { V as VireGlassGeometry } from './geometry-RhKd7CM5.cjs';
|
|
2
|
+
import { V as VireGlassOptics, o as VireGlassDebugMode } from './material-CnUmdKg1.cjs';
|
|
3
|
+
|
|
4
|
+
/** Smooth union with a second shape — bench morphing experiment only. */
|
|
5
|
+
type VireGlassMorph = {
|
|
6
|
+
offsetX: number;
|
|
7
|
+
offsetY: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
cornerRadius: number;
|
|
11
|
+
/** Seam smoothing radius in dp; 0 turns the second shape off. */
|
|
12
|
+
smoothing: number;
|
|
13
|
+
};
|
|
14
|
+
/** Surface response to a finger: the field around the touch point deforms, not the shape's
|
|
15
|
+
* bounding box (`vgTouchWarp` in `sdf.ts`). Lengths in dp; `radius` = 0 turns the response off
|
|
16
|
+
* entirely. */
|
|
17
|
+
type VireGlassTouch = {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
pullX: number;
|
|
21
|
+
pullY: number;
|
|
22
|
+
press: number;
|
|
23
|
+
radius: number;
|
|
24
|
+
waveAmp: number;
|
|
25
|
+
wavePhase: number;
|
|
26
|
+
};
|
|
27
|
+
/** Tinted glass for the primary action (M 16:08). Color is RGB 0…1. */
|
|
28
|
+
type VireGlassAccent = {
|
|
29
|
+
color: readonly [number, number, number];
|
|
30
|
+
amount?: number;
|
|
31
|
+
};
|
|
32
|
+
/** Default tint fraction: the color reads, but content beneath it is still visible. */
|
|
33
|
+
declare const ACCENT_AMOUNT: 0.8;
|
|
34
|
+
/** Magnification at the flat center. Kept separate from the uniform channel: it's also used by
|
|
35
|
+
* the fallback below Android 13, where there's no RuntimeShader and only an affine magnifier is
|
|
36
|
+
* left. */
|
|
37
|
+
declare const lensMagnify: (o: VireGlassOptics) => number;
|
|
38
|
+
/** Props for the native view. Besides the uniform channel, only what the view uses itself lives
|
|
39
|
+
* here: the shader source and the visible glass's size (the probe rectangle is taken from it). */
|
|
40
|
+
declare function toLensProps(optics: VireGlassOptics, geometry: VireGlassGeometry, density: number, options?: {
|
|
41
|
+
debug?: VireGlassDebugMode;
|
|
42
|
+
morph?: VireGlassMorph;
|
|
43
|
+
/** Third shape of the fused body; a zero size turns it off. */
|
|
44
|
+
morph2?: VireGlassMorph;
|
|
45
|
+
groupProbe?: number[];
|
|
46
|
+
touch?: VireGlassTouch;
|
|
47
|
+
/** Progress fraction, 0…1: to the left of the boundary the element is active. `undefined` means no progress. */
|
|
48
|
+
progress?: number;
|
|
49
|
+
/** Key light direction in screen space; defaults to the light at rest. */
|
|
50
|
+
light?: readonly [number, number];
|
|
51
|
+
/** 0…1: the lens builds up as the element appears — instead of a plain fade. */
|
|
52
|
+
appear?: number;
|
|
53
|
+
/** Tint for the primary action: the glass color and the fraction it lays over the content. */
|
|
54
|
+
accent?: VireGlassAccent;
|
|
55
|
+
}): {
|
|
56
|
+
uniformNames: string[];
|
|
57
|
+
uniformSizes: number[];
|
|
58
|
+
uniformValues: number[];
|
|
59
|
+
shaderSource: string;
|
|
60
|
+
glassWidth: number;
|
|
61
|
+
glassHeight: number;
|
|
62
|
+
};
|
|
63
|
+
/** Static part of the surface uniforms. Dynamics (gesture, press, light) get mixed in inside the
|
|
64
|
+
* component's worklet — the adapter must stay an ordinary function. */
|
|
65
|
+
declare function toSurfaceUniforms(optics: VireGlassOptics, geometry: VireGlassGeometry, options?: {
|
|
66
|
+
debug?: VireGlassDebugMode;
|
|
67
|
+
morph?: VireGlassMorph;
|
|
68
|
+
/** Third shape of the fused body; a zero size turns it off. */
|
|
69
|
+
morph2?: VireGlassMorph;
|
|
70
|
+
dragLimit?: number;
|
|
71
|
+
shadow?: number;
|
|
72
|
+
/** Average ambient color around the element: light from it bleeds into the shadow (reference 219 @8:22). */
|
|
73
|
+
ambient?: readonly [number, number, number];
|
|
74
|
+
/** The lens draws the glass body — the surface is left with the highlight, shadow and icon. */
|
|
75
|
+
bodyInLens?: boolean;
|
|
76
|
+
touch?: VireGlassTouch;
|
|
77
|
+
/** Progress fraction, 0…1: to the left of the boundary the element is active. `undefined` means no progress. */
|
|
78
|
+
progress?: number;
|
|
79
|
+
/** 0…1: the element is appearing — shadow and ink build up together with the lens. */
|
|
80
|
+
appear?: number;
|
|
81
|
+
/** 0 — the element sinks in under the finger, 1 — it rises into glass (reference §5). */
|
|
82
|
+
lift?: number;
|
|
83
|
+
}): {
|
|
84
|
+
u_center: number[];
|
|
85
|
+
u_halfSize: number[];
|
|
86
|
+
u_corner: number;
|
|
87
|
+
u_bevel: number;
|
|
88
|
+
u_thickness: number;
|
|
89
|
+
u_morphOffset: number[];
|
|
90
|
+
u_morphHalf: number[];
|
|
91
|
+
u_morphCorner: number;
|
|
92
|
+
u_morphK: number;
|
|
93
|
+
u_morph2Offset: number[];
|
|
94
|
+
u_morph2Half: number[];
|
|
95
|
+
u_morph2Corner: number;
|
|
96
|
+
u_edgeDensity: number;
|
|
97
|
+
u_dispersion: number;
|
|
98
|
+
u_refraction: number;
|
|
99
|
+
u_tint: number[];
|
|
100
|
+
u_shadow: number;
|
|
101
|
+
u_ambient: readonly [number, number, number];
|
|
102
|
+
u_shadowReach: number;
|
|
103
|
+
u_touch: number[];
|
|
104
|
+
u_pull: number[];
|
|
105
|
+
u_touchPress: number;
|
|
106
|
+
u_touchRadius: number;
|
|
107
|
+
u_wave: number[];
|
|
108
|
+
u_presence: number;
|
|
109
|
+
u_progress: number;
|
|
110
|
+
u_appear: number;
|
|
111
|
+
u_lift: number;
|
|
112
|
+
u_debug: number;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Surface fields that are LENGTHS: the adapter's contract is specified in dp, and on the web each
|
|
116
|
+
* one of them has to be multiplied by screen density. The list lives here rather than in the
|
|
117
|
+
* renderer, where it used to be a dozen and a half manual multiplications in a row: a missed
|
|
118
|
+
* field there was only caught by eye, and the miss isn't visible everywhere — at density 1,
|
|
119
|
+
* multiplying is indistinguishable from not doing it.
|
|
120
|
+
*/
|
|
121
|
+
type SurfaceUniforms = ReturnType<typeof toSurfaceUniforms>;
|
|
122
|
+
declare const SURFACE_LENGTH_UNIFORMS: readonly ["u_halfSize", "u_corner", "u_bevel", "u_morphOffset", "u_morphHalf", "u_morphCorner", "u_morphK", "u_morph2Offset", "u_morph2Half", "u_morph2Corner", "u_shadowReach", "u_touch", "u_pull", "u_touchRadius"];
|
|
123
|
+
/**
|
|
124
|
+
* Surface uniforms in device pixels. Android draws in dp and calls the adapter as-is; the web
|
|
125
|
+
* needs this conversion. `u_center` isn't part of it: the renderer knows the element's center on
|
|
126
|
+
* its own.
|
|
127
|
+
*/
|
|
128
|
+
declare function toDeviceSurfaceUniforms(raw: SurfaceUniforms, density: number): SurfaceUniforms;
|
|
129
|
+
/** Key light direction in screen coordinates, for when the orientation response is off. */
|
|
130
|
+
declare const REST_LIGHT: readonly [number, number];
|
|
131
|
+
/** Uniforms the component mixes in inside the worklet (press, active, light direction) and via
|
|
132
|
+
* the icon layer. Listed here so a test can check the shader contract's completeness without
|
|
133
|
+
* importing the component itself (it pulls in Skia and doesn't come up in a node environment). */
|
|
134
|
+
declare const DYNAMIC_UNIFORMS: readonly ["u_press", "u_active"];
|
|
135
|
+
declare const ICON_UNIFORMS: readonly ["u_iconOn", "u_iconScale", "u_inkIdle", "u_inkActive"];
|
|
136
|
+
/** App-colored overlay layer on the glass. The `u_overlay` sampler shares its contract with the
|
|
137
|
+
* ink mask and is sampled at the SAME coordinate — otherwise deformation would carry them apart. */
|
|
138
|
+
declare const OVERLAY_UNIFORMS: readonly ["u_overlayOn"];
|
|
139
|
+
declare function morphBetween(a: VireGlassGeometry, b: VireGlassGeometry, offsetX: number, offsetY: number, t: number): VireGlassMorph | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* MITOSIS: the second shape grows OUT OF the first and travels to its place, instead of appearing
|
|
142
|
+
* beside it at full size. A menu coming out of its button, a control dividing into segments.
|
|
143
|
+
*
|
|
144
|
+
* `morphBetween` is the other half — two shapes that are both already where they belong, fusing
|
|
145
|
+
* into one body — and run backwards it is meiosis, the neck thinning until it breaks. What neither
|
|
146
|
+
* of them may do is pop: at any `t` above zero this returns one continuous body, because that is
|
|
147
|
+
* the whole of what the reference says a material transition is.
|
|
148
|
+
*
|
|
149
|
+
* The choreography stays the host's: what the shapes MEAN is the app's business. How a silhouette
|
|
150
|
+
* emerges from another silhouette is the material's, the same way the spring under a finger is.
|
|
151
|
+
*/
|
|
152
|
+
declare function morphOutOf(source: VireGlassGeometry, target: VireGlassGeometry, offsetX: number, offsetY: number, t: number): VireGlassMorph | undefined;
|
|
153
|
+
|
|
154
|
+
export { ACCENT_AMOUNT as A, DYNAMIC_UNIFORMS as D, ICON_UNIFORMS as I, OVERLAY_UNIFORMS as O, REST_LIGHT as R, SURFACE_LENGTH_UNIFORMS as S, type VireGlassAccent as V, type SurfaceUniforms as a, type VireGlassMorph as b, type VireGlassTouch as c, morphOutOf as d, toLensProps as e, toSurfaceUniforms as f, lensMagnify as l, morphBetween as m, toDeviceSurfaceUniforms as t };
|