vireglass 1.0.0 → 2.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.
Files changed (97) hide show
  1. package/README.md +83 -9
  2. package/dist/adapters-BfeAopGO.d.ts +154 -0
  3. package/dist/adapters-DugC6Qri.d.cts +154 -0
  4. package/dist/chunk-3PGYF2NK.js +360 -0
  5. package/dist/chunk-3PGYF2NK.js.map +1 -0
  6. package/dist/{chunk-HF2AWZEZ.js → chunk-IQOBZGCF.js} +210 -606
  7. package/dist/chunk-IQOBZGCF.js.map +1 -0
  8. package/dist/chunk-JF3FK254.js +377 -0
  9. package/dist/chunk-JF3FK254.js.map +1 -0
  10. package/dist/chunk-P2ZOODXD.js +58 -0
  11. package/dist/chunk-P2ZOODXD.js.map +1 -0
  12. package/dist/chunk-TTOKBARR.js +456 -0
  13. package/dist/chunk-TTOKBARR.js.map +1 -0
  14. package/dist/dom.cjs +2055 -0
  15. package/dist/dom.cjs.map +1 -0
  16. package/dist/dom.d.cts +347 -0
  17. package/dist/dom.d.ts +347 -0
  18. package/dist/dom.js +1082 -0
  19. package/dist/dom.js.map +1 -0
  20. package/dist/geometry-GvXtt-_S.d.ts +105 -0
  21. package/dist/geometry-RhKd7CM5.d.cts +105 -0
  22. package/dist/group-model-8u4GKrUu.d.cts +194 -0
  23. package/dist/group-model-vYSmEVia.d.ts +194 -0
  24. package/dist/index.cjs +737 -244
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +122 -113
  27. package/dist/index.d.ts +122 -113
  28. package/dist/index.js +6 -277
  29. package/dist/index.js.map +1 -1
  30. package/dist/law.cjs +478 -0
  31. package/dist/law.cjs.map +1 -0
  32. package/dist/law.d.cts +543 -0
  33. package/dist/law.d.ts +543 -0
  34. package/dist/law.js +3 -0
  35. package/dist/law.js.map +1 -0
  36. package/dist/{material-CkUHUBoy.d.cts → material-CnUmdKg1.d.cts} +1 -1
  37. package/dist/{material-CkUHUBoy.d.ts → material-CnUmdKg1.d.ts} +1 -1
  38. package/dist/react.d.cts +1 -1
  39. package/dist/react.d.ts +1 -1
  40. package/dist/reference.cjs +221 -0
  41. package/dist/reference.cjs.map +1 -0
  42. package/dist/reference.d.cts +183 -0
  43. package/dist/reference.d.ts +183 -0
  44. package/dist/reference.js +197 -0
  45. package/dist/reference.js.map +1 -0
  46. package/dist/web/index.cjs +247 -165
  47. package/dist/web/index.cjs.map +1 -1
  48. package/dist/web/index.d.cts +4 -29
  49. package/dist/web/index.d.ts +4 -29
  50. package/dist/web/index.js +5 -90
  51. package/dist/web/index.js.map +1 -1
  52. package/docs/adr-001-rendering.md +288 -0
  53. package/docs/architecture.md +161 -0
  54. package/docs/benchmarks.md +191 -0
  55. package/docs/dom.md +160 -0
  56. package/docs/law.md +65 -0
  57. package/docs/material-lab.md +799 -0
  58. package/docs/platform-parity.md +266 -0
  59. package/docs/reference.md +397 -0
  60. package/package.json +24 -3
  61. package/src/accent.ts +35 -0
  62. package/src/accessibility.ts +30 -16
  63. package/src/adapters.ts +71 -3
  64. package/src/appear.ts +45 -0
  65. package/src/concentric.ts +66 -0
  66. package/src/dom/body.ts +98 -0
  67. package/src/dom/displacement.ts +163 -0
  68. package/src/dom/group.ts +124 -0
  69. package/src/dom/index.ts +739 -0
  70. package/src/dom/map-cache.ts +37 -0
  71. package/src/dom/nesting.ts +32 -0
  72. package/src/dom/preferences.ts +53 -0
  73. package/src/dom/probe.ts +163 -0
  74. package/src/dom/rim.ts +103 -0
  75. package/src/dom/scroll-edge.ts +106 -0
  76. package/src/dom/shadow.ts +56 -0
  77. package/src/dom/spectral-map.ts +102 -0
  78. package/src/dom/support.ts +47 -0
  79. package/src/geometry.ts +41 -14
  80. package/src/glass-scale.ts +3 -5
  81. package/src/index.ts +3 -1
  82. package/src/law.ts +562 -0
  83. package/src/lens-shader.ts +53 -30
  84. package/src/native/glass-surface.tsx +8 -14
  85. package/src/native/provider.tsx +22 -2
  86. package/src/optics.ts +43 -62
  87. package/src/reference.ts +9 -0
  88. package/src/scroll-edge.ts +22 -7
  89. package/src/sdf.ts +195 -8
  90. package/src/shadow-tint.ts +23 -0
  91. package/src/spectral.ts +110 -0
  92. package/src/surface-shader.ts +8 -6
  93. package/src/touch-response.ts +42 -27
  94. package/src/web/index.ts +0 -1
  95. package/dist/adapters-BPB0D5nr.d.cts +0 -357
  96. package/dist/adapters-BgSc-smX.d.ts +0 -357
  97. 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, one shader source, two render targets: **WebGL2** in the browser and
6
- **AGSL** on Android. Apache-2.0.
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.** The lens refracts only what the renderer drew itself, which is
87
- > why you hand it a `scene` callback that rasterises your backdrop into a 2D canvas. Glass over
88
- > live HTML is not supported in this release. If that is what you came for, this package does
89
- > not do it yet.
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 # 122 tests
161
- npm run check:glsl # both shaders compile and link as GLSL ES 3.0
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
- - **No glass over live DOM on the web.** See above.
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 };