vireglass 3.0.0 → 3.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 +30 -0
- package/dist/dom.cjs +199 -16
- package/dist/dom.cjs.map +1 -1
- package/dist/dom.d.cts +24 -2
- package/dist/dom.d.ts +24 -2
- package/dist/dom.js +198 -17
- package/dist/dom.js.map +1 -1
- package/package.json +2 -1
- package/src/dom/index.ts +175 -13
- package/src/dom/interim.ts +47 -0
- package/src/dom/rim.ts +6 -4
- package/src/dom/stats.ts +28 -0
package/README.md
CHANGED
|
@@ -153,6 +153,36 @@ glass.setMorph({ smoothing: 34, shape: { offsetX: 150, offsetY: -78, width: 170,
|
|
|
153
153
|
Two shapes joined through the smooth union — §5's merging and splitting. What the shapes mean is
|
|
154
154
|
your choreography; the material only knows how two silhouettes join.
|
|
155
155
|
|
|
156
|
+
### Morphing elements
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import { attachGlass, renderStats, resetRenderStats } from 'vireglass/dom';
|
|
160
|
+
|
|
161
|
+
glass.setInterim(true); // before a morph, a drag or a growth
|
|
162
|
+
// ...animate the element's box, and `setMorph` shapes if it flows into others...
|
|
163
|
+
glass.setInterim(false); // when it lands
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
A glass element that changes shape every frame used to re-run the whole pipeline every frame: a
|
|
167
|
+
backdrop probe, a full-resolution displacement map (and spectral map) and a new filter element.
|
|
168
|
+
That is the difference between 60 fps and 10 to 20. While interim, the element does none of it: it
|
|
169
|
+
reuses its last sample, keeps its filter, and the browser stretches the existing map over the live
|
|
170
|
+
box. The body, rim, shadow and custom properties still update every frame. A change of the morph
|
|
171
|
+
shapes passed to `setMorph`, of `setAppear` or of the system accessibility settings rebuilds the map
|
|
172
|
+
at reduced resolution and shows it in place, where the browser decodes lazily only once it has been
|
|
173
|
+
decoded. `setInterim(false)` does one full-resolution rebuild and one probe (with a supplied
|
|
174
|
+
`sample` it does not probe). Repeating a call is a no-op.
|
|
175
|
+
|
|
176
|
+
Always pair `setInterim(true)` with `setInterim(false)`. As a safety net an element that gets no call
|
|
177
|
+
at all for 2 seconds (no resize, morph, appear or update) leaves interim by itself, exactly as
|
|
178
|
+
`setInterim(false)` would, so a morph that never reported landing cannot leave the glass on a
|
|
179
|
+
stretched map. A pause longer than that in the middle of a morph ends interim early.
|
|
180
|
+
|
|
181
|
+
`renderStats()` returns `{ probes, fullBakes, reducedBakes, filterSwaps }`, counted since the last
|
|
182
|
+
`resetRenderStats()`. Every map counts: a rebuild with a spectral edge is two full bakes, one for
|
|
183
|
+
each map; a cache hit is none. It is the hook for a performance gate that counts work instead of
|
|
184
|
+
timing it: drive a morph, then assert the counters stayed at zero.
|
|
185
|
+
|
|
156
186
|
`attachGlass` writes CSS custom properties you can use directly:
|
|
157
187
|
|
|
158
188
|
| | |
|
package/dist/dom.cjs
CHANGED
|
@@ -1024,6 +1024,55 @@ function probeBackdrop(el, opts = {}) {
|
|
|
1024
1024
|
return statsFromSamples(samples);
|
|
1025
1025
|
}
|
|
1026
1026
|
|
|
1027
|
+
// src/dom/stats.ts
|
|
1028
|
+
var counts = { probes: 0, fullBakes: 0, reducedBakes: 0, filterSwaps: 0 };
|
|
1029
|
+
function renderStats() {
|
|
1030
|
+
return { ...counts };
|
|
1031
|
+
}
|
|
1032
|
+
function resetRenderStats() {
|
|
1033
|
+
counts.probes = 0;
|
|
1034
|
+
counts.fullBakes = 0;
|
|
1035
|
+
counts.reducedBakes = 0;
|
|
1036
|
+
counts.filterSwaps = 0;
|
|
1037
|
+
}
|
|
1038
|
+
function bump(key) {
|
|
1039
|
+
counts[key] += 1;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// src/dom/interim.ts
|
|
1043
|
+
function quantise(value, step = 2) {
|
|
1044
|
+
return Math.round(value / step) * step;
|
|
1045
|
+
}
|
|
1046
|
+
function interimKey(width, height, cornerRadius, morph, extra) {
|
|
1047
|
+
return `i|${quantise(width)}x${quantise(height)}r${quantise(cornerRadius)}|${morph}|${extra}`;
|
|
1048
|
+
}
|
|
1049
|
+
function filterSignature(blur2, ior, iorSpread2, hasHue) {
|
|
1050
|
+
return `${blur2}|${ior}|${iorSpread2 > 1e-4 ? iorSpread2 : 0}|${hasHue ? "h" : "-"}`;
|
|
1051
|
+
}
|
|
1052
|
+
function createLru(limit) {
|
|
1053
|
+
const store2 = /* @__PURE__ */ new Map();
|
|
1054
|
+
return {
|
|
1055
|
+
get(key) {
|
|
1056
|
+
const hit = store2.get(key);
|
|
1057
|
+
if (hit === void 0) return void 0;
|
|
1058
|
+
store2.delete(key);
|
|
1059
|
+
store2.set(key, hit);
|
|
1060
|
+
return hit;
|
|
1061
|
+
},
|
|
1062
|
+
set(key, value) {
|
|
1063
|
+
store2.delete(key);
|
|
1064
|
+
store2.set(key, value);
|
|
1065
|
+
if (store2.size > limit) {
|
|
1066
|
+
const oldest = store2.keys().next();
|
|
1067
|
+
if (!oldest.done) store2.delete(oldest.value);
|
|
1068
|
+
}
|
|
1069
|
+
},
|
|
1070
|
+
get size() {
|
|
1071
|
+
return store2.size;
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1027
1076
|
// src/dom/support.ts
|
|
1028
1077
|
var backdropFilterSupport = null;
|
|
1029
1078
|
var svgBackdropFilterSupport = null;
|
|
@@ -1338,9 +1387,11 @@ function rimGradientCss(optics, ambient, light, appear = 1) {
|
|
|
1338
1387
|
return `conic-gradient(from ${start.toFixed(1)}deg, ${line.join(", ")}), conic-gradient(${dark} 0deg, ${dark} 360deg)`;
|
|
1339
1388
|
}
|
|
1340
1389
|
var RIM_WIDTH_PX = RIM.widthPx;
|
|
1341
|
-
function contrastRimCss(bodyLuma, rimLuma) {
|
|
1390
|
+
function contrastRimCss(bodyLuma, rimLuma, appear = 1) {
|
|
1342
1391
|
const v = to2552(rimLuma);
|
|
1343
|
-
|
|
1392
|
+
const present = clamp016(appear);
|
|
1393
|
+
const colour = present >= 1 ? `rgb(${v},${v},${v})` : `rgba(${v},${v},${v},${present.toFixed(3)})`;
|
|
1394
|
+
return `conic-gradient(${colour} 0deg, ${colour} 360deg)`;
|
|
1344
1395
|
}
|
|
1345
1396
|
|
|
1346
1397
|
// src/dom/nesting.ts
|
|
@@ -1685,7 +1736,7 @@ function createGlassGroup(members, opts = {}) {
|
|
|
1685
1736
|
}
|
|
1686
1737
|
function update() {
|
|
1687
1738
|
if (destroyed) return;
|
|
1688
|
-
const
|
|
1739
|
+
const probe2 = opts.probe ?? probeBackdrop;
|
|
1689
1740
|
members.forEach(({ el, legibility }, index) => {
|
|
1690
1741
|
const rect = el.getBoundingClientRect();
|
|
1691
1742
|
if (rect.width <= 0 || rect.height <= 0) {
|
|
@@ -1696,7 +1747,7 @@ function createGlassGroup(members, opts = {}) {
|
|
|
1696
1747
|
String(index),
|
|
1697
1748
|
rect.left + rect.width / 2,
|
|
1698
1749
|
rect.top + rect.height / 2,
|
|
1699
|
-
|
|
1750
|
+
probe2(el),
|
|
1700
1751
|
legibility ?? 0
|
|
1701
1752
|
);
|
|
1702
1753
|
});
|
|
@@ -1860,6 +1911,18 @@ function fallbackFilterCss(optics) {
|
|
|
1860
1911
|
const saturate = 1 + optics.colorPickup;
|
|
1861
1912
|
return `blur(${blurPx}px) saturate(${saturate})`;
|
|
1862
1913
|
}
|
|
1914
|
+
function probe(el) {
|
|
1915
|
+
bump("probes");
|
|
1916
|
+
return probeBackdrop(el);
|
|
1917
|
+
}
|
|
1918
|
+
function decoded(url) {
|
|
1919
|
+
if (typeof Image === "undefined") return Promise.resolve();
|
|
1920
|
+
const img = new Image();
|
|
1921
|
+
img.src = url;
|
|
1922
|
+
return typeof img.decode === "function" ? img.decode().catch(() => void 0) : Promise.resolve();
|
|
1923
|
+
}
|
|
1924
|
+
var INTERIM_IDLE_MS = 2e3;
|
|
1925
|
+
var isEmpty = (g) => quantise(g.width) < 1 || quantise(g.height) < 1;
|
|
1863
1926
|
var to2553 = (v) => Math.round(Math.min(Math.max(v, 0), 1) * 255);
|
|
1864
1927
|
function rgbCss(r, g, b) {
|
|
1865
1928
|
return `rgb(${to2553(r)} ${to2553(g)} ${to2553(b)})`;
|
|
@@ -1886,6 +1949,13 @@ function attachGlass(el, opts = {}) {
|
|
|
1886
1949
|
let filterEl = null;
|
|
1887
1950
|
let destroyed = false;
|
|
1888
1951
|
let mapKey = "";
|
|
1952
|
+
let interim = false;
|
|
1953
|
+
let settling = false;
|
|
1954
|
+
let lastSample = null;
|
|
1955
|
+
let seq = 0;
|
|
1956
|
+
let shownSeq = 0;
|
|
1957
|
+
let idleTimer = null;
|
|
1958
|
+
const interimMaps = createLru(8);
|
|
1889
1959
|
let morph = null;
|
|
1890
1960
|
const onlyWhenTouched = opts.variant === "interactive";
|
|
1891
1961
|
let appear = onlyWhenTouched ? 0 : opts.appear ?? 1;
|
|
@@ -1897,6 +1967,7 @@ function attachGlass(el, opts = {}) {
|
|
|
1897
1967
|
mapKey = "";
|
|
1898
1968
|
deform.setElastic(elasticAllowed(opts.accessibility ?? a11y));
|
|
1899
1969
|
apply();
|
|
1970
|
+
if (interim) requestInterimMap();
|
|
1900
1971
|
});
|
|
1901
1972
|
warnIfNested(el);
|
|
1902
1973
|
const host = hostFor(el);
|
|
@@ -1922,24 +1993,111 @@ function attachGlass(el, opts = {}) {
|
|
|
1922
1993
|
const part = (s) => s ? `${s.offsetX},${s.offsetY},${s.width},${s.height},${s.cornerRadius}` : "-";
|
|
1923
1994
|
return `${morph.smoothing}/${part(morph.shape)}/${part(morph.shape2)}`;
|
|
1924
1995
|
}
|
|
1996
|
+
function invalidate() {
|
|
1997
|
+
seq += 1;
|
|
1998
|
+
shownSeq = seq;
|
|
1999
|
+
}
|
|
2000
|
+
function keepInterim() {
|
|
2001
|
+
if (idleTimer !== null) clearTimeout(idleTimer);
|
|
2002
|
+
idleTimer = setTimeout(leaveInterim, INTERIM_IDLE_MS);
|
|
2003
|
+
}
|
|
2004
|
+
function leaveInterim() {
|
|
2005
|
+
if (idleTimer !== null) clearTimeout(idleTimer);
|
|
2006
|
+
idleTimer = null;
|
|
2007
|
+
if (destroyed || !interim) return;
|
|
2008
|
+
interim = false;
|
|
2009
|
+
invalidate();
|
|
2010
|
+
mapKey = "";
|
|
2011
|
+
settling = true;
|
|
2012
|
+
apply();
|
|
2013
|
+
}
|
|
2014
|
+
function retarget(f, map, hue) {
|
|
2015
|
+
const images = f.querySelectorAll("feImage");
|
|
2016
|
+
images[0]?.setAttribute("href", map.url);
|
|
2017
|
+
if (hue) images[1]?.setAttribute("href", hue.url);
|
|
2018
|
+
for (const pass of f.querySelectorAll("feDisplacementMap")) {
|
|
2019
|
+
const ratio = Number(pass.getAttribute("data-vireglass-ratio") ?? 1);
|
|
2020
|
+
pass.setAttribute("scale", String(map.scale * (Number.isFinite(ratio) ? ratio : 1)));
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
function requestInterimMap() {
|
|
2024
|
+
if (!svgSupported || !filterEl || destroyed) return;
|
|
2025
|
+
const geometry = opts.geometry ?? measureGeometry(el);
|
|
2026
|
+
if (isEmpty(geometry)) return;
|
|
2027
|
+
const opticsNow = optics();
|
|
2028
|
+
const key = interimKey(
|
|
2029
|
+
geometry.width,
|
|
2030
|
+
geometry.height,
|
|
2031
|
+
geometry.cornerRadius,
|
|
2032
|
+
JSON.stringify([morph?.smoothing, morph?.shape, morph?.shape2, morph?.shapes]),
|
|
2033
|
+
`a${appear.toFixed(3)}:${opticsNow.refraction}:${opticsNow.refractionScale}:${opticsNow.bevelDp}`
|
|
2034
|
+
);
|
|
2035
|
+
let rec = interimMaps.get(key);
|
|
2036
|
+
if (!rec) {
|
|
2037
|
+
bump("reducedBakes");
|
|
2038
|
+
rec = { map: buildDisplacementMap(opticsNow, geometry, Math.min(1, devicePixelRatio()), morphState()), ready: false };
|
|
2039
|
+
interimMaps.set(key, rec);
|
|
2040
|
+
}
|
|
2041
|
+
const mine = seq += 1;
|
|
2042
|
+
const record = rec;
|
|
2043
|
+
const forFilter = filterEl;
|
|
2044
|
+
const show = () => {
|
|
2045
|
+
if (destroyed || filterEl !== forFilter || mine <= shownSeq) return;
|
|
2046
|
+
shownSeq = mine;
|
|
2047
|
+
retarget(forFilter, record.map, null);
|
|
2048
|
+
};
|
|
2049
|
+
if (record.ready) {
|
|
2050
|
+
show();
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
void decoded(record.map.url).then(() => {
|
|
2054
|
+
record.ready = true;
|
|
2055
|
+
show();
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
1925
2058
|
function apply() {
|
|
1926
2059
|
if (destroyed) return;
|
|
2060
|
+
if (interim) keepInterim();
|
|
1927
2061
|
const geometry = opts.geometry ?? measureGeometry(el);
|
|
1928
2062
|
const opticsNow = optics();
|
|
1929
|
-
const sample = supplied ??
|
|
2063
|
+
const sample = supplied ?? (interim && lastSample ? lastSample : probe(el));
|
|
2064
|
+
lastSample = sample;
|
|
1930
2065
|
const light = shouldInkBeLight(sample, wasLight);
|
|
1931
2066
|
wasLight = light;
|
|
1932
2067
|
const body = opts.body === false ? null : bodyCss(settledOptics(), sample, light ? 1 : 0, accent, appear);
|
|
1933
2068
|
if (svgSupported) {
|
|
1934
2069
|
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}`;
|
|
1935
|
-
if (key !== mapKey || !filterEl) {
|
|
1936
|
-
const map = cached(`d|${key}`, () =>
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
2070
|
+
if (interim && filterEl) ; else if (isEmpty(geometry)) ; else if (key !== mapKey || !filterEl) {
|
|
2071
|
+
const map = cached(`d|${key}`, () => {
|
|
2072
|
+
bump("fullBakes");
|
|
2073
|
+
return buildDisplacementMap(opticsNow, geometry, devicePixelRatio(), morphState());
|
|
2074
|
+
});
|
|
2075
|
+
const hue = hasSpectralEdge(opticsNow) ? cached(`h|${key}`, () => {
|
|
2076
|
+
bump("fullBakes");
|
|
2077
|
+
return buildSpectralMap(opticsNow, geometry, devicePixelRatio());
|
|
2078
|
+
}) : null;
|
|
2079
|
+
const signature = filterSignature(opticsNow.blur, opticsNow.ior, opticsNow.iorSpread, !!hue);
|
|
2080
|
+
if (settling && filterEl?.getAttribute("data-vireglass-signature") === signature) {
|
|
2081
|
+
settling = false;
|
|
2082
|
+
const mine = seq += 1;
|
|
2083
|
+
const forFilter = filterEl;
|
|
2084
|
+
const forKey = key;
|
|
2085
|
+
void Promise.all([decoded(map.url), hue ? decoded(hue.url) : void 0]).then(() => {
|
|
2086
|
+
if (destroyed || filterEl !== forFilter || mapKey !== forKey || mine <= shownSeq) return;
|
|
2087
|
+
shownSeq = mine;
|
|
2088
|
+
retarget(forFilter, map, hue);
|
|
2089
|
+
});
|
|
2090
|
+
} else {
|
|
2091
|
+
settling = false;
|
|
2092
|
+
invalidate();
|
|
2093
|
+
const defs = getFilterHost(host).querySelector("defs");
|
|
2094
|
+
const next = buildFilterElement(id, map.url, opticsNow, map.scale, hue);
|
|
2095
|
+
next.setAttribute("data-vireglass-signature", signature);
|
|
2096
|
+
if (filterEl?.parentNode) defs.replaceChild(next, filterEl);
|
|
2097
|
+
else defs.appendChild(next);
|
|
2098
|
+
bump("filterSwaps");
|
|
2099
|
+
filterEl = next;
|
|
2100
|
+
}
|
|
1943
2101
|
mapKey = key;
|
|
1944
2102
|
}
|
|
1945
2103
|
el.style.setProperty("backdrop-filter", `url(#${id})`);
|
|
@@ -1963,7 +2121,7 @@ function attachGlass(el, opts = {}) {
|
|
|
1963
2121
|
const pole = withPresence(resolveBody(opticsNow, sample, light ? 1 : 0), opticsNow).tintLuma;
|
|
1964
2122
|
el.style.setProperty(
|
|
1965
2123
|
"--vireglass-rim",
|
|
1966
|
-
(opts.accessibility ?? a11y).increaseContrast ? contrastRimCss(pole, contrastRimLuma(pole)) : rimGradientCss(opticsNow, [tr, tg, tb], opts.light ?? REST_LIGHT, appear)
|
|
2124
|
+
(opts.accessibility ?? a11y).increaseContrast ? contrastRimCss(pole, contrastRimLuma(pole), appear) : rimGradientCss(opticsNow, [tr, tg, tb], opts.light ?? REST_LIGHT, appear)
|
|
1967
2125
|
);
|
|
1968
2126
|
el.style.setProperty("--vireglass-rim-width", `${RIM_WIDTH_PX}px`);
|
|
1969
2127
|
el.style.setProperty("--vireglass-radius", `${geometry.cornerRadius}px`);
|
|
@@ -1986,7 +2144,9 @@ function attachGlass(el, opts = {}) {
|
|
|
1986
2144
|
const base = optics();
|
|
1987
2145
|
const rise = raiseIntoGlass(sampleOut.press);
|
|
1988
2146
|
const risen = optics({ ...opts.material, roughness: (opts.material?.roughness ?? VIREGLASS_MATERIAL.roughness) * rise.solid });
|
|
1989
|
-
|
|
2147
|
+
if (interim) keepInterim();
|
|
2148
|
+
bump("reducedBakes");
|
|
2149
|
+
const map = buildDisplacementMap(risen, geometry, 1, {
|
|
1990
2150
|
...morphState(),
|
|
1991
2151
|
touch: {
|
|
1992
2152
|
x: sampleOut.touchX,
|
|
@@ -1999,6 +2159,7 @@ function attachGlass(el, opts = {}) {
|
|
|
1999
2159
|
wavePhase: sampleOut.wavePhase
|
|
2000
2160
|
}
|
|
2001
2161
|
});
|
|
2162
|
+
invalidate();
|
|
2002
2163
|
if (filterEl) {
|
|
2003
2164
|
const feImage = filterEl.querySelector("feImage");
|
|
2004
2165
|
feImage?.setAttribute("href", map.url);
|
|
@@ -2021,7 +2182,7 @@ function attachGlass(el, opts = {}) {
|
|
|
2021
2182
|
el.style.setProperty("--vireglass-glow-opacity", "0");
|
|
2022
2183
|
return;
|
|
2023
2184
|
}
|
|
2024
|
-
const [gr, gg, gb] = ambientFrom(supplied ??
|
|
2185
|
+
const [gr, gg, gb] = ambientFrom(supplied ?? (interim && lastSample ? lastSample : probe(el)));
|
|
2025
2186
|
const cx = (x + geometry.width / 2) / geometry.width * 100;
|
|
2026
2187
|
const cy = (y + geometry.height / 2) / geometry.height * 100;
|
|
2027
2188
|
const reach = halfMinDp(geometry) * TOUCH_RADIUS_FRACTION;
|
|
@@ -2045,7 +2206,9 @@ function attachGlass(el, opts = {}) {
|
|
|
2045
2206
|
lastFrameAt = 0;
|
|
2046
2207
|
el.style.setProperty("--vireglass-glow-opacity", "0");
|
|
2047
2208
|
opts.onGlow?.(null);
|
|
2209
|
+
settling = !interim;
|
|
2048
2210
|
apply();
|
|
2211
|
+
if (interim) requestInterimMap();
|
|
2049
2212
|
return;
|
|
2050
2213
|
}
|
|
2051
2214
|
frame = requestAnimationFrame(tick);
|
|
@@ -2093,6 +2256,9 @@ function attachGlass(el, opts = {}) {
|
|
|
2093
2256
|
}
|
|
2094
2257
|
function destroy() {
|
|
2095
2258
|
destroyed = true;
|
|
2259
|
+
invalidate();
|
|
2260
|
+
if (idleTimer !== null) clearTimeout(idleTimer);
|
|
2261
|
+
idleTimer = null;
|
|
2096
2262
|
stopWatchingA11y();
|
|
2097
2263
|
if (attached.get(el) === handle) attached.delete(el);
|
|
2098
2264
|
if (frame !== null) cancelAnimationFrame(frame);
|
|
@@ -2134,6 +2300,7 @@ function attachGlass(el, opts = {}) {
|
|
|
2134
2300
|
if (next === appear) return;
|
|
2135
2301
|
appear = next;
|
|
2136
2302
|
apply();
|
|
2303
|
+
if (interim) requestInterimMap();
|
|
2137
2304
|
},
|
|
2138
2305
|
setAccent(next) {
|
|
2139
2306
|
accent = next ?? void 0;
|
|
@@ -2156,9 +2323,23 @@ function attachGlass(el, opts = {}) {
|
|
|
2156
2323
|
},
|
|
2157
2324
|
setMorph(next) {
|
|
2158
2325
|
morph = next && next.smoothing > 0 ? next : null;
|
|
2326
|
+
if (interim) {
|
|
2327
|
+
apply();
|
|
2328
|
+
requestInterimMap();
|
|
2329
|
+
return;
|
|
2330
|
+
}
|
|
2159
2331
|
mapKey = "";
|
|
2160
2332
|
apply();
|
|
2161
2333
|
},
|
|
2334
|
+
setInterim(on) {
|
|
2335
|
+
if (destroyed || on === interim) return;
|
|
2336
|
+
if (on) {
|
|
2337
|
+
interim = true;
|
|
2338
|
+
keepInterim();
|
|
2339
|
+
return;
|
|
2340
|
+
}
|
|
2341
|
+
leaveInterim();
|
|
2342
|
+
},
|
|
2162
2343
|
setSample(next) {
|
|
2163
2344
|
supplied = next ?? void 0;
|
|
2164
2345
|
apply();
|
|
@@ -2190,6 +2371,8 @@ exports.parseColor = parseColor;
|
|
|
2190
2371
|
exports.probeBackdrop = probeBackdrop;
|
|
2191
2372
|
exports.renderDisplacementPixels = renderDisplacementPixels;
|
|
2192
2373
|
exports.renderSpectralPixels = renderSpectralPixels;
|
|
2374
|
+
exports.renderStats = renderStats;
|
|
2375
|
+
exports.resetRenderStats = resetRenderStats;
|
|
2193
2376
|
exports.resetSupportCache = resetSupportCache;
|
|
2194
2377
|
exports.resolveBody = resolveBody;
|
|
2195
2378
|
exports.rimGradientCss = rimGradientCss;
|