vireglass 2.1.0 → 2.2.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 +2 -1
- package/dist/{chunk-BZC2WHCK.js → chunk-2XJJO7SC.js} +4 -4
- package/dist/{chunk-BZC2WHCK.js.map → chunk-2XJJO7SC.js.map} +1 -1
- package/dist/{chunk-3PGYF2NK.js → chunk-CTTZNZFV.js} +3 -3
- package/dist/{chunk-3PGYF2NK.js.map → chunk-CTTZNZFV.js.map} +1 -1
- package/dist/{chunk-FL5UZPY5.js → chunk-H5QTBF67.js} +4 -4
- package/dist/{chunk-FL5UZPY5.js.map → chunk-H5QTBF67.js.map} +1 -1
- package/dist/{chunk-TTOKBARR.js → chunk-MMPK6DCK.js} +10 -3
- package/dist/chunk-MMPK6DCK.js.map +1 -0
- package/dist/{chunk-P2ZOODXD.js → chunk-SLRPHDV7.js} +3 -3
- package/dist/{chunk-P2ZOODXD.js.map → chunk-SLRPHDV7.js.map} +1 -1
- package/dist/dom.cjs +48 -20
- package/dist/dom.cjs.map +1 -1
- package/dist/dom.d.cts +15 -3
- package/dist/dom.d.ts +15 -3
- package/dist/dom.js +44 -23
- package/dist/dom.js.map +1 -1
- package/dist/index.cjs +1 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -5
- package/dist/law.cjs +8 -1
- package/dist/law.cjs.map +1 -1
- package/dist/law.d.cts +7 -0
- package/dist/law.d.ts +7 -0
- package/dist/law.js +1 -1
- package/dist/reference.js +2 -2
- package/dist/web/index.cjs +1 -2
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.js +4 -4
- package/docs/law.md +2 -2
- package/package.json +11 -9
- package/src/dom/body.ts +24 -9
- package/src/dom/index.ts +43 -10
- package/src/dom/probe.ts +27 -3
- package/src/law.ts +7 -0
- package/dist/chunk-TTOKBARR.js.map +0 -1
package/dist/dom.d.cts
CHANGED
|
@@ -160,9 +160,21 @@ type GlassBody = {
|
|
|
160
160
|
declare function resolveBody(optics: VireGlassOptics, sample: BodyBackdrop, ink: number): GlassBody;
|
|
161
161
|
/**
|
|
162
162
|
* PRESENCE (§3): over a uniform backdrop there is nothing to refract and the glass honestly
|
|
163
|
-
* disappears — right for a piece of background, wrong for a control.
|
|
164
|
-
*
|
|
165
|
-
*
|
|
163
|
+
* disappears — right for a piece of background, wrong for a control. It is a MINIMUM, not an
|
|
164
|
+
* addition, so a body that already stands apart is left alone.
|
|
165
|
+
*
|
|
166
|
+
* The direction is the body's own. The previous version decided "lighter over dark, darker over
|
|
167
|
+
* light" from the backdrop alone, and then, when the body disagreed, clamped `tintLuma` to the
|
|
168
|
+
* backdrop's mean — the one value that separates from nothing. Light ink over a dark backdrop puts
|
|
169
|
+
* the body at 0.07 against a backdrop of 0.12: already separating, downward, and the clamp pulled
|
|
170
|
+
* it back onto the backdrop. Measured on the default material at presence 0.08: exactly 0.0000 at
|
|
171
|
+
* backdrops of 0.12, 0.20 and 0.35.
|
|
172
|
+
*
|
|
173
|
+
* What the demand is DIVIDED by is deliberately the distance to the tint's pole rather than to the
|
|
174
|
+
* body's own tint. Dividing by the latter is arithmetically tighter and asks for far more density
|
|
175
|
+
* wherever the two are close — enough to drive it to the ceiling over a dark backdrop and stop the
|
|
176
|
+
* glass being a window at all, which check:optics says plainly. Presence is a floor on visibility,
|
|
177
|
+
* not a licence to go opaque.
|
|
166
178
|
*/
|
|
167
179
|
declare function withPresence(body: GlassBody, optics: VireGlassOptics, sample: BodyBackdrop): GlassBody;
|
|
168
180
|
|
package/dist/dom.d.ts
CHANGED
|
@@ -160,9 +160,21 @@ type GlassBody = {
|
|
|
160
160
|
declare function resolveBody(optics: VireGlassOptics, sample: BodyBackdrop, ink: number): GlassBody;
|
|
161
161
|
/**
|
|
162
162
|
* PRESENCE (§3): over a uniform backdrop there is nothing to refract and the glass honestly
|
|
163
|
-
* disappears — right for a piece of background, wrong for a control.
|
|
164
|
-
*
|
|
165
|
-
*
|
|
163
|
+
* disappears — right for a piece of background, wrong for a control. It is a MINIMUM, not an
|
|
164
|
+
* addition, so a body that already stands apart is left alone.
|
|
165
|
+
*
|
|
166
|
+
* The direction is the body's own. The previous version decided "lighter over dark, darker over
|
|
167
|
+
* light" from the backdrop alone, and then, when the body disagreed, clamped `tintLuma` to the
|
|
168
|
+
* backdrop's mean — the one value that separates from nothing. Light ink over a dark backdrop puts
|
|
169
|
+
* the body at 0.07 against a backdrop of 0.12: already separating, downward, and the clamp pulled
|
|
170
|
+
* it back onto the backdrop. Measured on the default material at presence 0.08: exactly 0.0000 at
|
|
171
|
+
* backdrops of 0.12, 0.20 and 0.35.
|
|
172
|
+
*
|
|
173
|
+
* What the demand is DIVIDED by is deliberately the distance to the tint's pole rather than to the
|
|
174
|
+
* body's own tint. Dividing by the latter is arithmetically tighter and asks for far more density
|
|
175
|
+
* wherever the two are close — enough to drive it to the ceiling over a dark backdrop and stop the
|
|
176
|
+
* glass being a window at all, which check:optics says plainly. Presence is a floor on visibility,
|
|
177
|
+
* not a licence to go opaque.
|
|
166
178
|
*/
|
|
167
179
|
declare function withPresence(body: GlassBody, optics: VireGlassOptics, sample: BodyBackdrop): GlassBody;
|
|
168
180
|
|
package/dist/dom.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { shadowTint, NO_ACCESSIBILITY, createGroupState, createDeform, elasticAllowed, contrastRimLuma, concentricRadius, scrollEdgeStrength, scrollEdgeStyle, applyGlassScale, GLASS_SCALE_DEFAULT, applyAccessibility, applyAppear, accentTone, accentAmount, raiseIntoGlass } from './chunk-
|
|
1
|
+
import { shadowTint, NO_ACCESSIBILITY, createGroupState, createDeform, elasticAllowed, contrastRimLuma, concentricRadius, scrollEdgeStrength, scrollEdgeStyle, applyGlassScale, GLASS_SCALE_DEFAULT, applyAccessibility, applyAppear, accentTone, accentAmount, raiseIntoGlass } from './chunk-CTTZNZFV.js';
|
|
2
2
|
import { ambientFrom, shouldInkBeLight, INK_LIGHT, INK_DARK } from './chunk-JNRZNMJJ.js';
|
|
3
|
-
import { touchWarp, sceneDistance, sceneGradient, sdfRoundedRect, VIREGLASS_MATERIAL, REST_LIGHT, resolveOptics, refractionStrength } from './chunk-
|
|
4
|
-
import { shadowOpacity, bevelDp, thicknessDp, rimDp, shadowOpacityFrom, shadowReachDp, halfMinDp, MAX_STRETCH, roundedRectGeometry } from './chunk-
|
|
5
|
-
import { LENS, BODY, RIM, TOUCH, SHADOW, SHADOW_GAP, SCROLL_EDGE, BEVEL, SPECTRAL, DISPERSION } from './chunk-
|
|
3
|
+
import { touchWarp, sceneDistance, sceneGradient, sdfRoundedRect, VIREGLASS_MATERIAL, REST_LIGHT, resolveOptics, refractionStrength } from './chunk-H5QTBF67.js';
|
|
4
|
+
import { shadowOpacity, bevelDp, thicknessDp, rimDp, shadowOpacityFrom, shadowReachDp, halfMinDp, MAX_STRETCH, roundedRectGeometry } from './chunk-SLRPHDV7.js';
|
|
5
|
+
import { LENS, BODY, RIM, TOUCH, SHADOW, SHADOW_GAP, SCROLL_EDGE, BEVEL, SPECTRAL, DISPERSION } from './chunk-MMPK6DCK.js';
|
|
6
6
|
|
|
7
7
|
// src/dom/displacement.ts
|
|
8
8
|
var SCALE_GAIN = 0.75;
|
|
@@ -311,10 +311,18 @@ function sampleColorAt(el, x, y) {
|
|
|
311
311
|
}
|
|
312
312
|
const composited = compositeLayers(layers);
|
|
313
313
|
if (composited) return composited;
|
|
314
|
-
|
|
315
|
-
if (!topmost) return null;
|
|
316
|
-
return parseColor(getComputedStyle(topmost).color);
|
|
314
|
+
return canvasColor(el);
|
|
317
315
|
}
|
|
316
|
+
function canvasColor(el) {
|
|
317
|
+
const doc = el.ownerDocument;
|
|
318
|
+
for (const node of [doc.documentElement, doc.body]) {
|
|
319
|
+
if (!node) continue;
|
|
320
|
+
const bg = parseColor(getComputedStyle(node).backgroundColor);
|
|
321
|
+
if (bg && bg.a > 1e-3) return bg.a >= 0.999 ? bg : compositeLayers([bg, WHITE]);
|
|
322
|
+
}
|
|
323
|
+
return WHITE;
|
|
324
|
+
}
|
|
325
|
+
var WHITE = { r: 255, g: 255, b: 255, a: 1 };
|
|
318
326
|
function probeBackdrop(el, opts = {}) {
|
|
319
327
|
const cols = opts.cols ?? GRID_COLS;
|
|
320
328
|
const rows = opts.rows ?? GRID_ROWS;
|
|
@@ -417,15 +425,17 @@ function resolveBody(optics, sample, ink) {
|
|
|
417
425
|
function withPresence(body, optics, sample) {
|
|
418
426
|
if (optics.presence <= 0) return body;
|
|
419
427
|
const mean = clamp(sample.luma, 0, 1);
|
|
420
|
-
const
|
|
421
|
-
const
|
|
422
|
-
const separation = Math.abs(
|
|
428
|
+
const above = Math.abs(body.tintLuma - mean) > 1e-4 ? body.tintLuma > mean : mean < 0.5;
|
|
429
|
+
const pole = above ? TINT_LIGHT : TINT_DARK;
|
|
430
|
+
const separation = Math.min(optics.presence, Math.abs(pole - mean));
|
|
423
431
|
const reached = Math.abs(body.tintLuma - mean) * body.density;
|
|
424
432
|
if (reached >= separation) return body;
|
|
425
|
-
const needed = separation / Math.max(Math.abs(
|
|
433
|
+
const needed = separation / Math.max(Math.abs(pole - mean), 1e-4);
|
|
426
434
|
return {
|
|
427
|
-
density: Math.max(body.density, Math.min(needed,
|
|
428
|
-
|
|
435
|
+
density: Math.max(body.density, Math.min(needed, BODY.presenceDemand)),
|
|
436
|
+
// Left where the tint law put it, unless it landed exactly on the backdrop — which is the
|
|
437
|
+
// case that used to be created here rather than avoided.
|
|
438
|
+
tintLuma: Math.abs(body.tintLuma - mean) > 1e-4 ? body.tintLuma : pole
|
|
429
439
|
};
|
|
430
440
|
}
|
|
431
441
|
|
|
@@ -660,15 +670,22 @@ function waveImpulse(g) {
|
|
|
660
670
|
return halfMinDp(g) * MAX_STRETCH * WAVE_OF_TRAVEL;
|
|
661
671
|
}
|
|
662
672
|
var STYLE_ATTR = "data-vireglass-styles";
|
|
663
|
-
function
|
|
664
|
-
|
|
673
|
+
function hostFor(el) {
|
|
674
|
+
const root = el.getRootNode();
|
|
675
|
+
return root instanceof ShadowRoot ? root : el.ownerDocument ?? document;
|
|
676
|
+
}
|
|
677
|
+
function styleParent(host) {
|
|
678
|
+
return host instanceof ShadowRoot ? host : host.head;
|
|
679
|
+
}
|
|
680
|
+
function ensureRimStyles(host) {
|
|
681
|
+
if (host.querySelector(`style[${STYLE_ATTR}]`)) return;
|
|
665
682
|
const style = document.createElement("style");
|
|
666
683
|
style.setAttribute(STYLE_ATTR, "");
|
|
667
684
|
style.textContent = `[${GLASS_ATTR}]::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;padding:var(--vireglass-rim-width,1px);background:var(--vireglass-rim,none);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);mask-composite:exclude}[${GLASS_ATTR}]::before{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:var(--vireglass-glow,none);opacity:var(--vireglass-glow-opacity,0)}`;
|
|
668
|
-
|
|
685
|
+
styleParent(host).appendChild(style);
|
|
669
686
|
}
|
|
670
|
-
function getFilterHost() {
|
|
671
|
-
const existing =
|
|
687
|
+
function getFilterHost(host) {
|
|
688
|
+
const existing = host.querySelector(`svg[${FILTER_HOST_ATTR}]`);
|
|
672
689
|
if (existing) return existing;
|
|
673
690
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
674
691
|
svg.setAttribute(FILTER_HOST_ATTR, "");
|
|
@@ -678,7 +695,7 @@ function getFilterHost() {
|
|
|
678
695
|
svg.style.position = "absolute";
|
|
679
696
|
svg.style.pointerEvents = "none";
|
|
680
697
|
svg.appendChild(document.createElementNS(SVG_NS, "defs"));
|
|
681
|
-
|
|
698
|
+
(host instanceof ShadowRoot ? host : host.body).appendChild(svg);
|
|
682
699
|
return svg;
|
|
683
700
|
}
|
|
684
701
|
function buildFilterElement(id, mapUrl, optics, scale, spectral) {
|
|
@@ -716,6 +733,7 @@ function buildFilterElement(id, mapUrl, optics, scale, spectral) {
|
|
|
716
733
|
pass.setAttribute("xChannelSelector", "R");
|
|
717
734
|
pass.setAttribute("yChannelSelector", "G");
|
|
718
735
|
pass.setAttribute("result", `${name}raw`);
|
|
736
|
+
pass.setAttribute("data-vireglass-ratio", String(scale > 0 ? chScale / scale : 1));
|
|
719
737
|
const only = document.createElementNS(SVG_NS, "feColorMatrix");
|
|
720
738
|
only.setAttribute("in", `${name}raw`);
|
|
721
739
|
only.setAttribute("type", "matrix");
|
|
@@ -822,7 +840,8 @@ function attachGlass(el, opts = {}) {
|
|
|
822
840
|
apply();
|
|
823
841
|
});
|
|
824
842
|
warnIfNested(el);
|
|
825
|
-
|
|
843
|
+
const host = hostFor(el);
|
|
844
|
+
ensureRimStyles(host);
|
|
826
845
|
el.setAttribute(GLASS_ATTR, "");
|
|
827
846
|
const positionWasStatic = getComputedStyle(el).position === "static";
|
|
828
847
|
if (positionWasStatic) el.style.setProperty("position", "relative");
|
|
@@ -850,7 +869,7 @@ function attachGlass(el, opts = {}) {
|
|
|
850
869
|
const key = `a${appear.toFixed(3)}|m${morphKey()}|${geometry.width}x${geometry.height}r${geometry.cornerRadius}@${devicePixelRatio()}:${opticsNow.refraction}:${opticsNow.refractionScale}:${opticsNow.bevelDp}:${opticsNow.blur}`;
|
|
851
870
|
if (key !== mapKey || !filterEl) {
|
|
852
871
|
const map = cached(`d|${key}`, () => buildDisplacementMap(opticsNow, geometry, devicePixelRatio(), morphState()));
|
|
853
|
-
const defs = getFilterHost().querySelector("defs");
|
|
872
|
+
const defs = getFilterHost(host).querySelector("defs");
|
|
854
873
|
const hue = hasSpectralEdge(opticsNow) ? cached(`h|${key}`, () => buildSpectralMap(opticsNow, geometry, devicePixelRatio())) : null;
|
|
855
874
|
const next = buildFilterElement(id, map.url, opticsNow, map.scale, hue);
|
|
856
875
|
if (filterEl?.parentNode) defs.replaceChild(next, filterEl);
|
|
@@ -916,9 +935,11 @@ function attachGlass(el, opts = {}) {
|
|
|
916
935
|
});
|
|
917
936
|
if (filterEl) {
|
|
918
937
|
const feImage = filterEl.querySelector("feImage");
|
|
919
|
-
const feDisplace = filterEl.querySelector("feDisplacementMap");
|
|
920
938
|
feImage?.setAttribute("href", map.url);
|
|
921
|
-
|
|
939
|
+
for (const pass of filterEl.querySelectorAll("feDisplacementMap")) {
|
|
940
|
+
const ratio = Number(pass.getAttribute("data-vireglass-ratio") ?? 1);
|
|
941
|
+
pass.setAttribute("scale", String(map.scale * (Number.isFinite(ratio) ? ratio : 1)));
|
|
942
|
+
}
|
|
922
943
|
}
|
|
923
944
|
mapKey = "";
|
|
924
945
|
paintGlow(sampleOut.touchX, sampleOut.touchY, sampleOut.active * base.edgeLight, geometry);
|