vireglass 3.0.1 → 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 +194 -13
- package/dist/dom.cjs.map +1 -1
- package/dist/dom.d.cts +23 -1
- package/dist/dom.d.ts +23 -1
- package/dist/dom.js +193 -14
- package/dist/dom.js.map +1 -1
- package/package.json +2 -1
- package/src/dom/index.ts +174 -12
- package/src/dom/interim.ts +47 -0
- package/src/dom/stats.ts +28 -0
package/dist/dom.d.cts
CHANGED
|
@@ -309,6 +309,20 @@ declare function cached<T>(key: string, build: () => T): T;
|
|
|
309
309
|
declare function clearMapCache(): void;
|
|
310
310
|
declare function mapCacheSize(): number;
|
|
311
311
|
|
|
312
|
+
type RenderStats = {
|
|
313
|
+
/** `elementsFromPoint` backdrop probes. */
|
|
314
|
+
probes: number;
|
|
315
|
+
/** Displacement maps baked at full device resolution (cache hits are not bakes). */
|
|
316
|
+
fullBakes: number;
|
|
317
|
+
/** Displacement maps baked at reduced resolution: interim morphs and the finger path. */
|
|
318
|
+
reducedBakes: number;
|
|
319
|
+
/** Filter elements put into the shared `<defs>`, replacing or adding. */
|
|
320
|
+
filterSwaps: number;
|
|
321
|
+
};
|
|
322
|
+
/** The work the renderer has done since the last reset; the hook for a consumer's performance gate. */
|
|
323
|
+
declare function renderStats(): RenderStats;
|
|
324
|
+
declare function resetRenderStats(): void;
|
|
325
|
+
|
|
312
326
|
type AttachGlassOptions = {
|
|
313
327
|
material?: Partial<VireGlassMaterial>;
|
|
314
328
|
/** Defaults to the element's measured box (size + `border-radius`). */
|
|
@@ -405,6 +419,14 @@ type GlassHandle = {
|
|
|
405
419
|
strength: number;
|
|
406
420
|
} | null): void;
|
|
407
421
|
setMorph(morph: GlassMorph | null): void;
|
|
422
|
+
/**
|
|
423
|
+
* While on, the element is changing shape every frame (a morph, a drag, a growth). It stops
|
|
424
|
+
* probing the backdrop, stops rebuilding its maps and keeps its filter: the existing map is
|
|
425
|
+
* stretched over the live box. A change of `setMorph` shapes still updates the map, at reduced
|
|
426
|
+
* resolution and only once the new image has decoded. Turning it off does one full-resolution
|
|
427
|
+
* rebuild and one probe. Repeated calls with the same value do nothing.
|
|
428
|
+
*/
|
|
429
|
+
setInterim(on: boolean): void;
|
|
408
430
|
/**
|
|
409
431
|
* Replaces the backdrop the glass adapts to, without re-attaching, and repaints. The same
|
|
410
432
|
* object as `sample` in the options; `null` goes back to probing declared backgrounds.
|
|
@@ -414,4 +436,4 @@ type GlassHandle = {
|
|
|
414
436
|
};
|
|
415
437
|
declare function attachGlass(el: HTMLElement, opts?: AttachGlassOptions): GlassHandle;
|
|
416
438
|
|
|
417
|
-
export { type AttachGlassOptions, type BodyBackdrop, type BodyLayer, type DisplacementMap, type DisplacementState, type EdgePaint, type GlassBody, type GlassGroupHandle, type GlassGroupOptions, type GlassHandle, type GlassMorph, type GroupEntry, type ProbeOptions, RIM_WIDTH_PX, type RgbColor, type RimAmbient, type ScrollEdgeHandle, type ScrollEdgeOptions, type SpectralMap, ambientLuma, attachGlass, attachScrollEdge, bodyLayer, boxShadowCss, buildDisplacementMap, buildSpectralMap, cached, clearMapCache, compositeLayers, contrastRimCss, createGlassGroup, hasSpectralEdge, lightConicAngle, mapCacheSize, paintFor, parseColor, probeBackdrop, renderDisplacementPixels, renderSpectralPixels, resetSupportCache, resolveBody, rimGradientCss, rimLineAlpha, rimLobe, rimStrength, shadowAlphaFrom, statsFromSamples, supportsBackdropFilter, supportsSvgBackdropFilter, systemAccessibility, watchAccessibility, withPresence };
|
|
439
|
+
export { type AttachGlassOptions, type BodyBackdrop, type BodyLayer, type DisplacementMap, type DisplacementState, type EdgePaint, type GlassBody, type GlassGroupHandle, type GlassGroupOptions, type GlassHandle, type GlassMorph, type GroupEntry, type ProbeOptions, RIM_WIDTH_PX, type RenderStats, type RgbColor, type RimAmbient, type ScrollEdgeHandle, type ScrollEdgeOptions, type SpectralMap, ambientLuma, attachGlass, attachScrollEdge, bodyLayer, boxShadowCss, buildDisplacementMap, buildSpectralMap, cached, clearMapCache, compositeLayers, contrastRimCss, createGlassGroup, hasSpectralEdge, lightConicAngle, mapCacheSize, paintFor, parseColor, probeBackdrop, renderDisplacementPixels, renderSpectralPixels, renderStats, resetRenderStats, resetSupportCache, resolveBody, rimGradientCss, rimLineAlpha, rimLobe, rimStrength, shadowAlphaFrom, statsFromSamples, supportsBackdropFilter, supportsSvgBackdropFilter, systemAccessibility, watchAccessibility, withPresence };
|
package/dist/dom.d.ts
CHANGED
|
@@ -309,6 +309,20 @@ declare function cached<T>(key: string, build: () => T): T;
|
|
|
309
309
|
declare function clearMapCache(): void;
|
|
310
310
|
declare function mapCacheSize(): number;
|
|
311
311
|
|
|
312
|
+
type RenderStats = {
|
|
313
|
+
/** `elementsFromPoint` backdrop probes. */
|
|
314
|
+
probes: number;
|
|
315
|
+
/** Displacement maps baked at full device resolution (cache hits are not bakes). */
|
|
316
|
+
fullBakes: number;
|
|
317
|
+
/** Displacement maps baked at reduced resolution: interim morphs and the finger path. */
|
|
318
|
+
reducedBakes: number;
|
|
319
|
+
/** Filter elements put into the shared `<defs>`, replacing or adding. */
|
|
320
|
+
filterSwaps: number;
|
|
321
|
+
};
|
|
322
|
+
/** The work the renderer has done since the last reset; the hook for a consumer's performance gate. */
|
|
323
|
+
declare function renderStats(): RenderStats;
|
|
324
|
+
declare function resetRenderStats(): void;
|
|
325
|
+
|
|
312
326
|
type AttachGlassOptions = {
|
|
313
327
|
material?: Partial<VireGlassMaterial>;
|
|
314
328
|
/** Defaults to the element's measured box (size + `border-radius`). */
|
|
@@ -405,6 +419,14 @@ type GlassHandle = {
|
|
|
405
419
|
strength: number;
|
|
406
420
|
} | null): void;
|
|
407
421
|
setMorph(morph: GlassMorph | null): void;
|
|
422
|
+
/**
|
|
423
|
+
* While on, the element is changing shape every frame (a morph, a drag, a growth). It stops
|
|
424
|
+
* probing the backdrop, stops rebuilding its maps and keeps its filter: the existing map is
|
|
425
|
+
* stretched over the live box. A change of `setMorph` shapes still updates the map, at reduced
|
|
426
|
+
* resolution and only once the new image has decoded. Turning it off does one full-resolution
|
|
427
|
+
* rebuild and one probe. Repeated calls with the same value do nothing.
|
|
428
|
+
*/
|
|
429
|
+
setInterim(on: boolean): void;
|
|
408
430
|
/**
|
|
409
431
|
* Replaces the backdrop the glass adapts to, without re-attaching, and repaints. The same
|
|
410
432
|
* object as `sample` in the options; `null` goes back to probing declared backgrounds.
|
|
@@ -414,4 +436,4 @@ type GlassHandle = {
|
|
|
414
436
|
};
|
|
415
437
|
declare function attachGlass(el: HTMLElement, opts?: AttachGlassOptions): GlassHandle;
|
|
416
438
|
|
|
417
|
-
export { type AttachGlassOptions, type BodyBackdrop, type BodyLayer, type DisplacementMap, type DisplacementState, type EdgePaint, type GlassBody, type GlassGroupHandle, type GlassGroupOptions, type GlassHandle, type GlassMorph, type GroupEntry, type ProbeOptions, RIM_WIDTH_PX, type RgbColor, type RimAmbient, type ScrollEdgeHandle, type ScrollEdgeOptions, type SpectralMap, ambientLuma, attachGlass, attachScrollEdge, bodyLayer, boxShadowCss, buildDisplacementMap, buildSpectralMap, cached, clearMapCache, compositeLayers, contrastRimCss, createGlassGroup, hasSpectralEdge, lightConicAngle, mapCacheSize, paintFor, parseColor, probeBackdrop, renderDisplacementPixels, renderSpectralPixels, resetSupportCache, resolveBody, rimGradientCss, rimLineAlpha, rimLobe, rimStrength, shadowAlphaFrom, statsFromSamples, supportsBackdropFilter, supportsSvgBackdropFilter, systemAccessibility, watchAccessibility, withPresence };
|
|
439
|
+
export { type AttachGlassOptions, type BodyBackdrop, type BodyLayer, type DisplacementMap, type DisplacementState, type EdgePaint, type GlassBody, type GlassGroupHandle, type GlassGroupOptions, type GlassHandle, type GlassMorph, type GroupEntry, type ProbeOptions, RIM_WIDTH_PX, type RenderStats, type RgbColor, type RimAmbient, type ScrollEdgeHandle, type ScrollEdgeOptions, type SpectralMap, ambientLuma, attachGlass, attachScrollEdge, bodyLayer, boxShadowCss, buildDisplacementMap, buildSpectralMap, cached, clearMapCache, compositeLayers, contrastRimCss, createGlassGroup, hasSpectralEdge, lightConicAngle, mapCacheSize, paintFor, parseColor, probeBackdrop, renderDisplacementPixels, renderSpectralPixels, renderStats, resetRenderStats, resetSupportCache, resolveBody, rimGradientCss, rimLineAlpha, rimLobe, rimStrength, shadowAlphaFrom, statsFromSamples, supportsBackdropFilter, supportsSvgBackdropFilter, systemAccessibility, watchAccessibility, withPresence };
|
package/dist/dom.js
CHANGED
|
@@ -340,6 +340,55 @@ function probeBackdrop(el, opts = {}) {
|
|
|
340
340
|
return statsFromSamples(samples);
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
+
// src/dom/stats.ts
|
|
344
|
+
var counts = { probes: 0, fullBakes: 0, reducedBakes: 0, filterSwaps: 0 };
|
|
345
|
+
function renderStats() {
|
|
346
|
+
return { ...counts };
|
|
347
|
+
}
|
|
348
|
+
function resetRenderStats() {
|
|
349
|
+
counts.probes = 0;
|
|
350
|
+
counts.fullBakes = 0;
|
|
351
|
+
counts.reducedBakes = 0;
|
|
352
|
+
counts.filterSwaps = 0;
|
|
353
|
+
}
|
|
354
|
+
function bump(key) {
|
|
355
|
+
counts[key] += 1;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// src/dom/interim.ts
|
|
359
|
+
function quantise(value, step = 2) {
|
|
360
|
+
return Math.round(value / step) * step;
|
|
361
|
+
}
|
|
362
|
+
function interimKey(width, height, cornerRadius, morph, extra) {
|
|
363
|
+
return `i|${quantise(width)}x${quantise(height)}r${quantise(cornerRadius)}|${morph}|${extra}`;
|
|
364
|
+
}
|
|
365
|
+
function filterSignature(blur, ior, iorSpread, hasHue) {
|
|
366
|
+
return `${blur}|${ior}|${iorSpread > 1e-4 ? iorSpread : 0}|${hasHue ? "h" : "-"}`;
|
|
367
|
+
}
|
|
368
|
+
function createLru(limit) {
|
|
369
|
+
const store2 = /* @__PURE__ */ new Map();
|
|
370
|
+
return {
|
|
371
|
+
get(key) {
|
|
372
|
+
const hit = store2.get(key);
|
|
373
|
+
if (hit === void 0) return void 0;
|
|
374
|
+
store2.delete(key);
|
|
375
|
+
store2.set(key, hit);
|
|
376
|
+
return hit;
|
|
377
|
+
},
|
|
378
|
+
set(key, value) {
|
|
379
|
+
store2.delete(key);
|
|
380
|
+
store2.set(key, value);
|
|
381
|
+
if (store2.size > limit) {
|
|
382
|
+
const oldest = store2.keys().next();
|
|
383
|
+
if (!oldest.done) store2.delete(oldest.value);
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
get size() {
|
|
387
|
+
return store2.size;
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
343
392
|
// src/dom/support.ts
|
|
344
393
|
var backdropFilterSupport = null;
|
|
345
394
|
var svgBackdropFilterSupport = null;
|
|
@@ -679,7 +728,7 @@ function createGlassGroup(members, opts = {}) {
|
|
|
679
728
|
}
|
|
680
729
|
function update() {
|
|
681
730
|
if (destroyed) return;
|
|
682
|
-
const
|
|
731
|
+
const probe2 = opts.probe ?? probeBackdrop;
|
|
683
732
|
members.forEach(({ el, legibility }, index) => {
|
|
684
733
|
const rect = el.getBoundingClientRect();
|
|
685
734
|
if (rect.width <= 0 || rect.height <= 0) {
|
|
@@ -690,7 +739,7 @@ function createGlassGroup(members, opts = {}) {
|
|
|
690
739
|
String(index),
|
|
691
740
|
rect.left + rect.width / 2,
|
|
692
741
|
rect.top + rect.height / 2,
|
|
693
|
-
|
|
742
|
+
probe2(el),
|
|
694
743
|
legibility ?? 0
|
|
695
744
|
);
|
|
696
745
|
});
|
|
@@ -854,6 +903,18 @@ function fallbackFilterCss(optics) {
|
|
|
854
903
|
const saturate = 1 + optics.colorPickup;
|
|
855
904
|
return `blur(${blurPx}px) saturate(${saturate})`;
|
|
856
905
|
}
|
|
906
|
+
function probe(el) {
|
|
907
|
+
bump("probes");
|
|
908
|
+
return probeBackdrop(el);
|
|
909
|
+
}
|
|
910
|
+
function decoded(url) {
|
|
911
|
+
if (typeof Image === "undefined") return Promise.resolve();
|
|
912
|
+
const img = new Image();
|
|
913
|
+
img.src = url;
|
|
914
|
+
return typeof img.decode === "function" ? img.decode().catch(() => void 0) : Promise.resolve();
|
|
915
|
+
}
|
|
916
|
+
var INTERIM_IDLE_MS = 2e3;
|
|
917
|
+
var isEmpty = (g) => quantise(g.width) < 1 || quantise(g.height) < 1;
|
|
857
918
|
var to2553 = (v) => Math.round(Math.min(Math.max(v, 0), 1) * 255);
|
|
858
919
|
function rgbCss(r, g, b) {
|
|
859
920
|
return `rgb(${to2553(r)} ${to2553(g)} ${to2553(b)})`;
|
|
@@ -880,6 +941,13 @@ function attachGlass(el, opts = {}) {
|
|
|
880
941
|
let filterEl = null;
|
|
881
942
|
let destroyed = false;
|
|
882
943
|
let mapKey = "";
|
|
944
|
+
let interim = false;
|
|
945
|
+
let settling = false;
|
|
946
|
+
let lastSample = null;
|
|
947
|
+
let seq = 0;
|
|
948
|
+
let shownSeq = 0;
|
|
949
|
+
let idleTimer = null;
|
|
950
|
+
const interimMaps = createLru(8);
|
|
883
951
|
let morph = null;
|
|
884
952
|
const onlyWhenTouched = opts.variant === "interactive";
|
|
885
953
|
let appear = onlyWhenTouched ? 0 : opts.appear ?? 1;
|
|
@@ -891,6 +959,7 @@ function attachGlass(el, opts = {}) {
|
|
|
891
959
|
mapKey = "";
|
|
892
960
|
deform.setElastic(elasticAllowed(opts.accessibility ?? a11y));
|
|
893
961
|
apply();
|
|
962
|
+
if (interim) requestInterimMap();
|
|
894
963
|
});
|
|
895
964
|
warnIfNested(el);
|
|
896
965
|
const host = hostFor(el);
|
|
@@ -916,24 +985,111 @@ function attachGlass(el, opts = {}) {
|
|
|
916
985
|
const part = (s) => s ? `${s.offsetX},${s.offsetY},${s.width},${s.height},${s.cornerRadius}` : "-";
|
|
917
986
|
return `${morph.smoothing}/${part(morph.shape)}/${part(morph.shape2)}`;
|
|
918
987
|
}
|
|
988
|
+
function invalidate() {
|
|
989
|
+
seq += 1;
|
|
990
|
+
shownSeq = seq;
|
|
991
|
+
}
|
|
992
|
+
function keepInterim() {
|
|
993
|
+
if (idleTimer !== null) clearTimeout(idleTimer);
|
|
994
|
+
idleTimer = setTimeout(leaveInterim, INTERIM_IDLE_MS);
|
|
995
|
+
}
|
|
996
|
+
function leaveInterim() {
|
|
997
|
+
if (idleTimer !== null) clearTimeout(idleTimer);
|
|
998
|
+
idleTimer = null;
|
|
999
|
+
if (destroyed || !interim) return;
|
|
1000
|
+
interim = false;
|
|
1001
|
+
invalidate();
|
|
1002
|
+
mapKey = "";
|
|
1003
|
+
settling = true;
|
|
1004
|
+
apply();
|
|
1005
|
+
}
|
|
1006
|
+
function retarget(f, map, hue) {
|
|
1007
|
+
const images = f.querySelectorAll("feImage");
|
|
1008
|
+
images[0]?.setAttribute("href", map.url);
|
|
1009
|
+
if (hue) images[1]?.setAttribute("href", hue.url);
|
|
1010
|
+
for (const pass of f.querySelectorAll("feDisplacementMap")) {
|
|
1011
|
+
const ratio = Number(pass.getAttribute("data-vireglass-ratio") ?? 1);
|
|
1012
|
+
pass.setAttribute("scale", String(map.scale * (Number.isFinite(ratio) ? ratio : 1)));
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
function requestInterimMap() {
|
|
1016
|
+
if (!svgSupported || !filterEl || destroyed) return;
|
|
1017
|
+
const geometry = opts.geometry ?? measureGeometry(el);
|
|
1018
|
+
if (isEmpty(geometry)) return;
|
|
1019
|
+
const opticsNow = optics();
|
|
1020
|
+
const key = interimKey(
|
|
1021
|
+
geometry.width,
|
|
1022
|
+
geometry.height,
|
|
1023
|
+
geometry.cornerRadius,
|
|
1024
|
+
JSON.stringify([morph?.smoothing, morph?.shape, morph?.shape2, morph?.shapes]),
|
|
1025
|
+
`a${appear.toFixed(3)}:${opticsNow.refraction}:${opticsNow.refractionScale}:${opticsNow.bevelDp}`
|
|
1026
|
+
);
|
|
1027
|
+
let rec = interimMaps.get(key);
|
|
1028
|
+
if (!rec) {
|
|
1029
|
+
bump("reducedBakes");
|
|
1030
|
+
rec = { map: buildDisplacementMap(opticsNow, geometry, Math.min(1, devicePixelRatio()), morphState()), ready: false };
|
|
1031
|
+
interimMaps.set(key, rec);
|
|
1032
|
+
}
|
|
1033
|
+
const mine = seq += 1;
|
|
1034
|
+
const record = rec;
|
|
1035
|
+
const forFilter = filterEl;
|
|
1036
|
+
const show = () => {
|
|
1037
|
+
if (destroyed || filterEl !== forFilter || mine <= shownSeq) return;
|
|
1038
|
+
shownSeq = mine;
|
|
1039
|
+
retarget(forFilter, record.map, null);
|
|
1040
|
+
};
|
|
1041
|
+
if (record.ready) {
|
|
1042
|
+
show();
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
void decoded(record.map.url).then(() => {
|
|
1046
|
+
record.ready = true;
|
|
1047
|
+
show();
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
919
1050
|
function apply() {
|
|
920
1051
|
if (destroyed) return;
|
|
1052
|
+
if (interim) keepInterim();
|
|
921
1053
|
const geometry = opts.geometry ?? measureGeometry(el);
|
|
922
1054
|
const opticsNow = optics();
|
|
923
|
-
const sample = supplied ??
|
|
1055
|
+
const sample = supplied ?? (interim && lastSample ? lastSample : probe(el));
|
|
1056
|
+
lastSample = sample;
|
|
924
1057
|
const light = shouldInkBeLight(sample, wasLight);
|
|
925
1058
|
wasLight = light;
|
|
926
1059
|
const body = opts.body === false ? null : bodyCss(settledOptics(), sample, light ? 1 : 0, accent, appear);
|
|
927
1060
|
if (svgSupported) {
|
|
928
1061
|
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}`;
|
|
929
|
-
if (key !== mapKey || !filterEl) {
|
|
930
|
-
const map = cached(`d|${key}`, () =>
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1062
|
+
if (interim && filterEl) ; else if (isEmpty(geometry)) ; else if (key !== mapKey || !filterEl) {
|
|
1063
|
+
const map = cached(`d|${key}`, () => {
|
|
1064
|
+
bump("fullBakes");
|
|
1065
|
+
return buildDisplacementMap(opticsNow, geometry, devicePixelRatio(), morphState());
|
|
1066
|
+
});
|
|
1067
|
+
const hue = hasSpectralEdge(opticsNow) ? cached(`h|${key}`, () => {
|
|
1068
|
+
bump("fullBakes");
|
|
1069
|
+
return buildSpectralMap(opticsNow, geometry, devicePixelRatio());
|
|
1070
|
+
}) : null;
|
|
1071
|
+
const signature = filterSignature(opticsNow.blur, opticsNow.ior, opticsNow.iorSpread, !!hue);
|
|
1072
|
+
if (settling && filterEl?.getAttribute("data-vireglass-signature") === signature) {
|
|
1073
|
+
settling = false;
|
|
1074
|
+
const mine = seq += 1;
|
|
1075
|
+
const forFilter = filterEl;
|
|
1076
|
+
const forKey = key;
|
|
1077
|
+
void Promise.all([decoded(map.url), hue ? decoded(hue.url) : void 0]).then(() => {
|
|
1078
|
+
if (destroyed || filterEl !== forFilter || mapKey !== forKey || mine <= shownSeq) return;
|
|
1079
|
+
shownSeq = mine;
|
|
1080
|
+
retarget(forFilter, map, hue);
|
|
1081
|
+
});
|
|
1082
|
+
} else {
|
|
1083
|
+
settling = false;
|
|
1084
|
+
invalidate();
|
|
1085
|
+
const defs = getFilterHost(host).querySelector("defs");
|
|
1086
|
+
const next = buildFilterElement(id, map.url, opticsNow, map.scale, hue);
|
|
1087
|
+
next.setAttribute("data-vireglass-signature", signature);
|
|
1088
|
+
if (filterEl?.parentNode) defs.replaceChild(next, filterEl);
|
|
1089
|
+
else defs.appendChild(next);
|
|
1090
|
+
bump("filterSwaps");
|
|
1091
|
+
filterEl = next;
|
|
1092
|
+
}
|
|
937
1093
|
mapKey = key;
|
|
938
1094
|
}
|
|
939
1095
|
el.style.setProperty("backdrop-filter", `url(#${id})`);
|
|
@@ -980,7 +1136,9 @@ function attachGlass(el, opts = {}) {
|
|
|
980
1136
|
const base = optics();
|
|
981
1137
|
const rise = raiseIntoGlass(sampleOut.press);
|
|
982
1138
|
const risen = optics({ ...opts.material, roughness: (opts.material?.roughness ?? VIREGLASS_MATERIAL.roughness) * rise.solid });
|
|
983
|
-
|
|
1139
|
+
if (interim) keepInterim();
|
|
1140
|
+
bump("reducedBakes");
|
|
1141
|
+
const map = buildDisplacementMap(risen, geometry, 1, {
|
|
984
1142
|
...morphState(),
|
|
985
1143
|
touch: {
|
|
986
1144
|
x: sampleOut.touchX,
|
|
@@ -993,6 +1151,7 @@ function attachGlass(el, opts = {}) {
|
|
|
993
1151
|
wavePhase: sampleOut.wavePhase
|
|
994
1152
|
}
|
|
995
1153
|
});
|
|
1154
|
+
invalidate();
|
|
996
1155
|
if (filterEl) {
|
|
997
1156
|
const feImage = filterEl.querySelector("feImage");
|
|
998
1157
|
feImage?.setAttribute("href", map.url);
|
|
@@ -1015,7 +1174,7 @@ function attachGlass(el, opts = {}) {
|
|
|
1015
1174
|
el.style.setProperty("--vireglass-glow-opacity", "0");
|
|
1016
1175
|
return;
|
|
1017
1176
|
}
|
|
1018
|
-
const [gr, gg, gb] = ambientFrom(supplied ??
|
|
1177
|
+
const [gr, gg, gb] = ambientFrom(supplied ?? (interim && lastSample ? lastSample : probe(el)));
|
|
1019
1178
|
const cx = (x + geometry.width / 2) / geometry.width * 100;
|
|
1020
1179
|
const cy = (y + geometry.height / 2) / geometry.height * 100;
|
|
1021
1180
|
const reach = halfMinDp(geometry) * TOUCH_RADIUS_FRACTION;
|
|
@@ -1039,7 +1198,9 @@ function attachGlass(el, opts = {}) {
|
|
|
1039
1198
|
lastFrameAt = 0;
|
|
1040
1199
|
el.style.setProperty("--vireglass-glow-opacity", "0");
|
|
1041
1200
|
opts.onGlow?.(null);
|
|
1201
|
+
settling = !interim;
|
|
1042
1202
|
apply();
|
|
1203
|
+
if (interim) requestInterimMap();
|
|
1043
1204
|
return;
|
|
1044
1205
|
}
|
|
1045
1206
|
frame = requestAnimationFrame(tick);
|
|
@@ -1087,6 +1248,9 @@ function attachGlass(el, opts = {}) {
|
|
|
1087
1248
|
}
|
|
1088
1249
|
function destroy() {
|
|
1089
1250
|
destroyed = true;
|
|
1251
|
+
invalidate();
|
|
1252
|
+
if (idleTimer !== null) clearTimeout(idleTimer);
|
|
1253
|
+
idleTimer = null;
|
|
1090
1254
|
stopWatchingA11y();
|
|
1091
1255
|
if (attached.get(el) === handle) attached.delete(el);
|
|
1092
1256
|
if (frame !== null) cancelAnimationFrame(frame);
|
|
@@ -1128,6 +1292,7 @@ function attachGlass(el, opts = {}) {
|
|
|
1128
1292
|
if (next === appear) return;
|
|
1129
1293
|
appear = next;
|
|
1130
1294
|
apply();
|
|
1295
|
+
if (interim) requestInterimMap();
|
|
1131
1296
|
},
|
|
1132
1297
|
setAccent(next) {
|
|
1133
1298
|
accent = next ?? void 0;
|
|
@@ -1150,9 +1315,23 @@ function attachGlass(el, opts = {}) {
|
|
|
1150
1315
|
},
|
|
1151
1316
|
setMorph(next) {
|
|
1152
1317
|
morph = next && next.smoothing > 0 ? next : null;
|
|
1318
|
+
if (interim) {
|
|
1319
|
+
apply();
|
|
1320
|
+
requestInterimMap();
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1153
1323
|
mapKey = "";
|
|
1154
1324
|
apply();
|
|
1155
1325
|
},
|
|
1326
|
+
setInterim(on) {
|
|
1327
|
+
if (destroyed || on === interim) return;
|
|
1328
|
+
if (on) {
|
|
1329
|
+
interim = true;
|
|
1330
|
+
keepInterim();
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
leaveInterim();
|
|
1334
|
+
},
|
|
1156
1335
|
setSample(next) {
|
|
1157
1336
|
supplied = next ?? void 0;
|
|
1158
1337
|
apply();
|
|
@@ -1163,6 +1342,6 @@ function attachGlass(el, opts = {}) {
|
|
|
1163
1342
|
return handle;
|
|
1164
1343
|
}
|
|
1165
1344
|
|
|
1166
|
-
export { RIM_WIDTH_PX, ambientLuma, attachGlass, attachScrollEdge, bodyLayer, boxShadowCss, buildDisplacementMap, buildSpectralMap, cached, clearMapCache, compositeLayers, contrastRimCss, createGlassGroup, hasSpectralEdge, lightConicAngle, mapCacheSize, paintFor, parseColor, probeBackdrop, renderDisplacementPixels, renderSpectralPixels, resetSupportCache, resolveBody, rimGradientCss, rimLineAlpha, rimLobe, rimStrength, shadowAlphaFrom, statsFromSamples, supportsBackdropFilter, supportsSvgBackdropFilter, systemAccessibility, watchAccessibility, withPresence };
|
|
1345
|
+
export { RIM_WIDTH_PX, ambientLuma, attachGlass, attachScrollEdge, bodyLayer, boxShadowCss, buildDisplacementMap, buildSpectralMap, cached, clearMapCache, compositeLayers, contrastRimCss, createGlassGroup, hasSpectralEdge, lightConicAngle, mapCacheSize, paintFor, parseColor, probeBackdrop, renderDisplacementPixels, renderSpectralPixels, renderStats, resetRenderStats, resetSupportCache, resolveBody, rimGradientCss, rimLineAlpha, rimLobe, rimStrength, shadowAlphaFrom, statsFromSamples, supportsBackdropFilter, supportsSvgBackdropFilter, systemAccessibility, watchAccessibility, withPresence };
|
|
1167
1346
|
//# sourceMappingURL=dom.js.map
|
|
1168
1347
|
//# sourceMappingURL=dom.js.map
|