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/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 probe = opts.probe ?? probeBackdrop;
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
- probe(el),
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 ?? probeBackdrop(el);
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}`, () => buildDisplacementMap(opticsNow, geometry, devicePixelRatio(), morphState()));
931
- const defs = getFilterHost(host).querySelector("defs");
932
- const hue = hasSpectralEdge(opticsNow) ? cached(`h|${key}`, () => buildSpectralMap(opticsNow, geometry, devicePixelRatio())) : null;
933
- const next = buildFilterElement(id, map.url, opticsNow, map.scale, hue);
934
- if (filterEl?.parentNode) defs.replaceChild(next, filterEl);
935
- else defs.appendChild(next);
936
- filterEl = next;
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
- const map = buildDisplacementMap(risen, geometry, interacting ? 1 : devicePixelRatio(), {
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 ?? probeBackdrop(el));
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