@filip.mazev/blocks 1.4.13 → 1.4.15
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 +5 -5
- package/core/styles/_a11y.scss +1 -1
- package/core/styles/_index.scss +3 -9
- package/core/styles/_palettes.scss +54 -10
- package/core/styles/themes/_azure-ember-theme.scss +4 -0
- package/core/styles/themes/_brick-rose-cyan-theme.scss +4 -0
- package/core/styles/themes/_carbon-cobalt-theme.scss +4 -0
- package/effects/effects.css +120 -8
- package/fesm2022/filip.mazev-blocks-core.mjs +20 -31
- package/fesm2022/filip.mazev-blocks-core.mjs.map +1 -1
- package/fesm2022/filip.mazev-blocks-effects-runtime.mjs +167 -46
- package/fesm2022/filip.mazev-blocks-effects-runtime.mjs.map +1 -1
- package/fesm2022/filip.mazev-blocks-forms.mjs +12 -12
- package/fesm2022/filip.mazev-blocks-forms.mjs.map +1 -1
- package/fesm2022/filip.mazev-blocks.mjs +1 -1
- package/fesm2022/filip.mazev-blocks.mjs.map +1 -1
- package/package.json +1 -1
- package/schematics/ng-add/index.d.ts +1 -10
- package/schematics/ng-add/index.js +4 -13
- package/schematics/ng-add/schema.json +11 -17
- package/types/filip.mazev-blocks-core.d.ts +4 -13
- package/types/filip.mazev-blocks-effects-runtime.d.ts +2 -0
- package/types/filip.mazev-blocks.d.ts +1 -1
- package/core/styles/themes/_azure-coral-theme.scss +0 -4
- package/core/styles/themes/_blue-theme.scss +0 -5
- package/core/styles/themes/_graphite-sky-blue-theme.scss +0 -19
- package/core/styles/themes/_green-theme.scss +0 -5
- package/core/styles/themes/_orange-theme.scss +0 -5
- package/core/styles/themes/_purple-theme.scss +0 -5
- package/core/styles/themes/_red-theme.scss +0 -5
- package/core/styles/themes/_scarlet-cyan-theme.scss +0 -4
- package/core/styles/themes/_white-theme.scss +0 -5
|
@@ -31,6 +31,7 @@ function configureAppearance(root, initial = {}) {
|
|
|
31
31
|
if (configured.has(root)) throw new Error("A glass configuration is already mounted on this root.");
|
|
32
32
|
configured.add(root);
|
|
33
33
|
const restoreAttributes = rememberAttributes(root, attributes);
|
|
34
|
+
const originalAttributes = new Map(attributes.map((name) => [name, root.getAttribute(name)]));
|
|
34
35
|
const restoreStyles = rememberStyles(root, properties);
|
|
35
36
|
let options = { ...initial };
|
|
36
37
|
let disposed = false;
|
|
@@ -38,27 +39,34 @@ function configureAppearance(root, initial = {}) {
|
|
|
38
39
|
const viewEvent = root.ownerDocument.defaultView?.CustomEvent;
|
|
39
40
|
if (viewEvent) root.ownerDocument.dispatchEvent(new viewEvent(configurationEvent, { detail: root }));
|
|
40
41
|
};
|
|
41
|
-
const paint = () => {
|
|
42
|
-
restoreAttributes();
|
|
43
|
-
restoreStyles();
|
|
42
|
+
const paint = (sync = true) => {
|
|
44
43
|
const values = [
|
|
45
44
|
["data-bx-glass-quality", options.quality],
|
|
46
45
|
["data-bx-reduced-motion", options.reducedMotion],
|
|
47
46
|
["data-bx-reduced-transparency", options.reducedTransparency]
|
|
48
47
|
];
|
|
49
|
-
for (const [name, value] of values)
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
for (const [name, value] of values) {
|
|
49
|
+
const next = value === void 0 ? originalAttributes.get(name) ?? null : String(value);
|
|
50
|
+
if (root.getAttribute(name) === next) continue;
|
|
51
|
+
if (next === null) root.removeAttribute(name);
|
|
52
|
+
else root.setAttribute(name, next);
|
|
53
|
+
}
|
|
54
|
+
if (options.glassiness !== void 0) {
|
|
55
|
+
const next = String(finiteClamp(options.glassiness, 0, 1, .5));
|
|
56
|
+
if (root.style.getPropertyValue("--bx-glassiness") !== next) root.style.setProperty("--bx-glassiness", next);
|
|
57
|
+
} else restoreStyles();
|
|
58
|
+
if (sync) notify();
|
|
52
59
|
};
|
|
53
60
|
paint();
|
|
54
61
|
return {
|
|
55
62
|
update(next) {
|
|
56
63
|
if (!disposed) {
|
|
64
|
+
const previous = options;
|
|
57
65
|
options = {
|
|
58
66
|
...options,
|
|
59
67
|
...next
|
|
60
68
|
};
|
|
61
|
-
paint();
|
|
69
|
+
paint(previous.quality !== options.quality || previous.reducedMotion !== options.reducedMotion || previous.reducedTransparency !== options.reducedTransparency);
|
|
62
70
|
}
|
|
63
71
|
},
|
|
64
72
|
destroy() {
|
|
@@ -246,7 +254,7 @@ function lightingVisibility(doc, view) {
|
|
|
246
254
|
};
|
|
247
255
|
}
|
|
248
256
|
const sampleInterval = 180;
|
|
249
|
-
const liveInterval =
|
|
257
|
+
const liveInterval = 16;
|
|
250
258
|
const rasterSize = 32;
|
|
251
259
|
var AmbientSampler = class {
|
|
252
260
|
doc;
|
|
@@ -256,6 +264,7 @@ var AmbientSampler = class {
|
|
|
256
264
|
samples = /* @__PURE__ */ new Map();
|
|
257
265
|
dirty = /* @__PURE__ */ new Set();
|
|
258
266
|
pending = /* @__PURE__ */ new Set();
|
|
267
|
+
urgent = /* @__PURE__ */ new Set();
|
|
259
268
|
sources = /* @__PURE__ */ new Set();
|
|
260
269
|
initialized = false;
|
|
261
270
|
media = /* @__PURE__ */ new WeakMap();
|
|
@@ -296,15 +305,31 @@ var AmbientSampler = class {
|
|
|
296
305
|
this.samples.delete(entry);
|
|
297
306
|
this.dirty.delete(entry);
|
|
298
307
|
this.pending.delete(entry);
|
|
308
|
+
this.urgent.delete(entry);
|
|
299
309
|
this.syncLive();
|
|
300
310
|
}
|
|
301
311
|
lights(entry) {
|
|
302
|
-
|
|
312
|
+
const sample = this.samples.get(entry);
|
|
313
|
+
if (!sample) return [];
|
|
314
|
+
const dx = entry.bounds && sample.bounds ? entry.bounds.left - sample.bounds.left : 0;
|
|
315
|
+
const dy = entry.bounds && sample.bounds ? entry.bounds.top - sample.bounds.top : 0;
|
|
316
|
+
return dx || dy ? sample.lights.map((light) => ({
|
|
317
|
+
...light,
|
|
318
|
+
x: light.x + dx,
|
|
319
|
+
y: light.y + dy
|
|
320
|
+
})) : sample.lights;
|
|
303
321
|
}
|
|
304
|
-
invalidate(entry) {
|
|
305
|
-
for (const receiver of entry ? [entry] : this.samples.keys())
|
|
322
|
+
invalidate(entry, immediate = false) {
|
|
323
|
+
for (const receiver of entry ? Array.isArray(entry) ? entry : [entry] : this.samples.keys()) {
|
|
324
|
+
if (!receiver.visible || !receiver.element.isConnected) continue;
|
|
325
|
+
if (!this.pending.has(receiver)) this.dirty.add(receiver);
|
|
326
|
+
if (immediate) this.urgent.add(receiver);
|
|
327
|
+
}
|
|
306
328
|
this.resume();
|
|
307
329
|
}
|
|
330
|
+
isPending(entry) {
|
|
331
|
+
return this.urgent.has(entry);
|
|
332
|
+
}
|
|
308
333
|
assetChanged(element) {
|
|
309
334
|
this.media.delete(element);
|
|
310
335
|
this.invalidate();
|
|
@@ -324,6 +349,13 @@ var AmbientSampler = class {
|
|
|
324
349
|
this.pending.clear();
|
|
325
350
|
return;
|
|
326
351
|
}
|
|
352
|
+
if (this.urgent.size) {
|
|
353
|
+
if (this.timer !== void 0) this.view.clearTimeout(this.timer);
|
|
354
|
+
this.timer = void 0;
|
|
355
|
+
for (const entry of this.dirty) this.pending.add(entry);
|
|
356
|
+
this.dirty.clear();
|
|
357
|
+
this.stopFrame ??= subscribeFrame(() => this.sampleBatch());
|
|
358
|
+
}
|
|
327
359
|
if (this.dirty.size && this.timer === void 0 && !this.stopFrame) this.timer = this.view.setTimeout(() => {
|
|
328
360
|
this.timer = void 0;
|
|
329
361
|
this.nextSample = this.view.performance.now() + sampleInterval;
|
|
@@ -342,6 +374,7 @@ var AmbientSampler = class {
|
|
|
342
374
|
this.samples.clear();
|
|
343
375
|
this.dirty.clear();
|
|
344
376
|
this.pending.clear();
|
|
377
|
+
this.urgent.clear();
|
|
345
378
|
this.sources.clear();
|
|
346
379
|
this.media = /* @__PURE__ */ new WeakMap();
|
|
347
380
|
this.initialized = false;
|
|
@@ -365,15 +398,19 @@ var AmbientSampler = class {
|
|
|
365
398
|
const rasterSamples = /* @__PURE__ */ new Map();
|
|
366
399
|
const sources = [...this.sources];
|
|
367
400
|
const completed = [];
|
|
368
|
-
for (const entry of this.pending) {
|
|
401
|
+
for (const entry of /* @__PURE__ */ new Set([...this.urgent, ...this.pending])) {
|
|
369
402
|
this.pending.delete(entry);
|
|
403
|
+
this.urgent.delete(entry);
|
|
370
404
|
if (!entry.visible || !entry.element.isConnected || !this.samples.has(entry)) continue;
|
|
371
405
|
entry.bounds = entry.element.getBoundingClientRect();
|
|
406
|
+
const bounds = entry.bounds;
|
|
407
|
+
if (bounds.bottom <= 0 || bounds.right <= 0 || bounds.top >= this.view.innerHeight || bounds.left >= this.view.innerWidth) continue;
|
|
372
408
|
this.dependencies = /* @__PURE__ */ new Set();
|
|
373
409
|
const lights = this.environmentLights(entry, sources, rasterSamples, rects, visibility);
|
|
374
410
|
const mediaRects = /* @__PURE__ */ new Map();
|
|
375
411
|
for (const source of this.dependencies) mediaRects.set(source, this.rectFor(source, rects));
|
|
376
412
|
this.samples.set(entry, {
|
|
413
|
+
bounds,
|
|
377
414
|
lights,
|
|
378
415
|
media: this.dependencies,
|
|
379
416
|
rects: mediaRects
|
|
@@ -385,6 +422,7 @@ var AmbientSampler = class {
|
|
|
385
422
|
for (const entry of completed) this.changed(entry);
|
|
386
423
|
if (this.pending.size) return true;
|
|
387
424
|
this.stopFrame = void 0;
|
|
425
|
+
this.nextSample = this.view.performance.now() + sampleInterval;
|
|
388
426
|
this.resume();
|
|
389
427
|
return false;
|
|
390
428
|
}
|
|
@@ -393,6 +431,8 @@ var AmbientSampler = class {
|
|
|
393
431
|
for (const [entry, sample] of this.samples) {
|
|
394
432
|
const motion = inheritedAttribute(entry.element, "data-bx-reduced-motion");
|
|
395
433
|
if (!entry.visible || !entry.element.isConnected || (motion === null ? this.motion.matches : motion === "true")) continue;
|
|
434
|
+
const bounds = entry.bounds;
|
|
435
|
+
if (bounds && (bounds.bottom <= 0 || bounds.right <= 0 || bounds.top >= this.view.innerHeight || bounds.left >= this.view.innerWidth)) continue;
|
|
396
436
|
for (const source of sample.media) {
|
|
397
437
|
if (!source.isConnected || !/^(CANVAS|VIDEO)$/.test(source.tagName) || this.media.get(source)?.data === null) continue;
|
|
398
438
|
if (source.tagName === "VIDEO" && source.paused) continue;
|
|
@@ -426,6 +466,7 @@ var AmbientSampler = class {
|
|
|
426
466
|
const sample = this.samples.get(entry);
|
|
427
467
|
if (!sample || coverageChanged || this.dirty.has(entry) || this.pending.has(entry)) {
|
|
428
468
|
this.dirty.add(entry);
|
|
469
|
+
this.urgent.add(entry);
|
|
429
470
|
continue;
|
|
430
471
|
}
|
|
431
472
|
const pixels = /* @__PURE__ */ new Map([[source, next?.data ?? null]]);
|
|
@@ -442,12 +483,12 @@ var AmbientSampler = class {
|
|
|
442
483
|
}
|
|
443
484
|
}
|
|
444
485
|
for (const entry of recolored) this.changed(entry);
|
|
445
|
-
this.liveDelay = changed ? liveInterval : Math.min(
|
|
486
|
+
this.liveDelay = changed ? liveInterval : Math.min(250, this.liveDelay * 2);
|
|
446
487
|
this.resume();
|
|
447
488
|
}, this.liveDelay);
|
|
448
489
|
}
|
|
449
490
|
samePixels(first, second, alphaOnly = false) {
|
|
450
|
-
for (let index = alphaOnly ? 3 : 0; index < first.data.length; index += alphaOnly ? 4 : 1) if (first.data[index] >> 3 !== second.data[index] >> 3) return false;
|
|
491
|
+
for (let index = alphaOnly ? 3 : 0; index < first.data.length; index += alphaOnly ? 4 : 1) if (alphaOnly ? first.data[index] >> 3 !== second.data[index] >> 3 : Math.abs(first.data[index] - second.data[index]) >= 2) return false;
|
|
451
492
|
return true;
|
|
452
493
|
}
|
|
453
494
|
readRaster(element, refresh = false) {
|
|
@@ -736,11 +777,46 @@ var AmbientSampler = class {
|
|
|
736
777
|
v = (y - bounds.top - offset(positionY, bounds.height - height * scale)) / (height * scale);
|
|
737
778
|
if (u < 0 || u > 1 || v < 0 || v > 1) return void 0;
|
|
738
779
|
}
|
|
739
|
-
const px = Math.max(0, Math.min(data.width - 1,
|
|
740
|
-
const
|
|
741
|
-
const
|
|
780
|
+
const px = Math.max(0, Math.min(data.width - 1, u * data.width - .5));
|
|
781
|
+
const py = Math.max(0, Math.min(data.height - 1, v * data.height - .5));
|
|
782
|
+
const left = Math.floor(px), top = Math.floor(py);
|
|
783
|
+
const right = Math.min(data.width - 1, left + 1), bottom = Math.min(data.height - 1, top + 1);
|
|
784
|
+
const taps = [
|
|
785
|
+
[
|
|
786
|
+
left,
|
|
787
|
+
top,
|
|
788
|
+
(1 - (px - left)) * (1 - (py - top))
|
|
789
|
+
],
|
|
790
|
+
[
|
|
791
|
+
right,
|
|
792
|
+
top,
|
|
793
|
+
(px - left) * (1 - (py - top))
|
|
794
|
+
],
|
|
795
|
+
[
|
|
796
|
+
left,
|
|
797
|
+
bottom,
|
|
798
|
+
(1 - (px - left)) * (py - top)
|
|
799
|
+
],
|
|
800
|
+
[
|
|
801
|
+
right,
|
|
802
|
+
bottom,
|
|
803
|
+
(px - left) * (py - top)
|
|
804
|
+
]
|
|
805
|
+
];
|
|
806
|
+
const channels = [
|
|
807
|
+
0,
|
|
808
|
+
0,
|
|
809
|
+
0
|
|
810
|
+
];
|
|
811
|
+
let alpha = 0;
|
|
812
|
+
for (const [x, y, weight] of taps) {
|
|
813
|
+
const offset = (y * data.width + x) * 4;
|
|
814
|
+
const coverage = data.data[offset + 3] / 255 * weight;
|
|
815
|
+
alpha += coverage;
|
|
816
|
+
for (let channel = 0; channel < 3; channel++) channels[channel] += data.data[offset + channel] * coverage;
|
|
817
|
+
}
|
|
742
818
|
if (alpha < .08) return void 0;
|
|
743
|
-
return `rgb(${
|
|
819
|
+
return `rgb(${channels.map((channel) => Math.round(channel / alpha)).join(" ")} / ${alpha.toFixed(2)})`;
|
|
744
820
|
}
|
|
745
821
|
gradientColorAt(image, bounds, x, y) {
|
|
746
822
|
if (!image.includes("gradient(")) return void 0;
|
|
@@ -768,7 +844,10 @@ var AmbientSampler = class {
|
|
|
768
844
|
const v = (y - (bounds.top + bounds.height / 2)) / Math.max(1, bounds.height / 2);
|
|
769
845
|
amount = Math.max(0, Math.min(1, Math.hypot(u, v) / Math.SQRT2));
|
|
770
846
|
}
|
|
771
|
-
|
|
847
|
+
const position = amount * (colors.length - 1);
|
|
848
|
+
const index = Math.min(colors.length - 1, Math.floor(position));
|
|
849
|
+
if (index === colors.length - 1 || position === index) return colors[index];
|
|
850
|
+
return `color-mix(in srgb, ${colors[index]} ${((1 - (position - index)) * 100).toFixed(2)}%, ${colors[index + 1]})`;
|
|
772
851
|
}
|
|
773
852
|
isTransparent(color) {
|
|
774
853
|
const value = color.trim().toLowerCase();
|
|
@@ -941,13 +1020,25 @@ var SceneRuntime = class {
|
|
|
941
1020
|
this.refresh();
|
|
942
1021
|
};
|
|
943
1022
|
refresh = () => {
|
|
944
|
-
this.
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1023
|
+
this.refreshEntries([...this.entries.values()]);
|
|
1024
|
+
};
|
|
1025
|
+
scroll = (event) => {
|
|
1026
|
+
const root = event.target;
|
|
1027
|
+
if (root?.nodeType !== 1) {
|
|
1028
|
+
this.refresh();
|
|
1029
|
+
return;
|
|
949
1030
|
}
|
|
950
|
-
|
|
1031
|
+
const area = root.getBoundingClientRect();
|
|
1032
|
+
const nearby = [];
|
|
1033
|
+
this.refreshEntries([...this.entries.values()].filter((entry) => {
|
|
1034
|
+
if (!entry.visible) return false;
|
|
1035
|
+
if (root.contains(entry.element)) return true;
|
|
1036
|
+
const bounds = entry.bounds ??= entry.element.getBoundingClientRect();
|
|
1037
|
+
if (bounds.right > area.left && bounds.left < area.right && bounds.bottom > area.top && bounds.top < area.bottom) return true;
|
|
1038
|
+
if (bounds.right >= area.left - 160 && bounds.left <= area.right + 160 && bounds.bottom >= area.top - 160 && bounds.top <= area.bottom + 160) nearby.push(entry);
|
|
1039
|
+
return false;
|
|
1040
|
+
}));
|
|
1041
|
+
this.ambient.invalidate(nearby);
|
|
951
1042
|
};
|
|
952
1043
|
constructor(doc) {
|
|
953
1044
|
this.doc = doc;
|
|
@@ -965,11 +1056,11 @@ var SceneRuntime = class {
|
|
|
965
1056
|
for (const record of records) {
|
|
966
1057
|
const entry = this.entries.get(record.target);
|
|
967
1058
|
if (!entry) continue;
|
|
1059
|
+
if (record.isIntersecting && !entry.visible) entry.resuming = true;
|
|
968
1060
|
entry.visible = record.isIntersecting;
|
|
969
|
-
this.ambient.invalidate(entry);
|
|
1061
|
+
this.ambient.invalidate(entry, true);
|
|
970
1062
|
if (entry.visible) {
|
|
971
1063
|
entry.bounds = void 0;
|
|
972
|
-
entry.lastLighting = void 0;
|
|
973
1064
|
this.queue.add(entry);
|
|
974
1065
|
}
|
|
975
1066
|
}
|
|
@@ -1058,7 +1149,7 @@ var SceneRuntime = class {
|
|
|
1058
1149
|
if (entry) this.updateSelected(entry);
|
|
1059
1150
|
this.updateEmitter();
|
|
1060
1151
|
if (entry) {
|
|
1061
|
-
this.ambient.invalidate(entry);
|
|
1152
|
+
this.ambient.invalidate(entry, true);
|
|
1062
1153
|
entry.bounds = void 0;
|
|
1063
1154
|
entry.lastLighting = void 0;
|
|
1064
1155
|
this.queue.add(entry);
|
|
@@ -1097,6 +1188,14 @@ var SceneRuntime = class {
|
|
|
1097
1188
|
}
|
|
1098
1189
|
};
|
|
1099
1190
|
}
|
|
1191
|
+
refreshEntries(entries) {
|
|
1192
|
+
this.ambient.invalidate(entries, true);
|
|
1193
|
+
for (const entry of entries) {
|
|
1194
|
+
entry.bounds = void 0;
|
|
1195
|
+
if (entry.visible) this.queue.add(entry);
|
|
1196
|
+
}
|
|
1197
|
+
this.schedule();
|
|
1198
|
+
}
|
|
1100
1199
|
isLightingDecoration(node) {
|
|
1101
1200
|
if (node.nodeType !== node.ELEMENT_NODE) return true;
|
|
1102
1201
|
const element = node;
|
|
@@ -1208,7 +1307,7 @@ var SceneRuntime = class {
|
|
|
1208
1307
|
this.doc.addEventListener("pointerleave", this.leave, { passive: true });
|
|
1209
1308
|
this.view.addEventListener("blur", this.blur);
|
|
1210
1309
|
this.view.addEventListener("resize", this.refresh, { passive: true });
|
|
1211
|
-
this.doc.addEventListener("scroll", this.
|
|
1310
|
+
this.doc.addEventListener("scroll", this.scroll, {
|
|
1212
1311
|
passive: true,
|
|
1213
1312
|
capture: true
|
|
1214
1313
|
});
|
|
@@ -1243,7 +1342,7 @@ var SceneRuntime = class {
|
|
|
1243
1342
|
this.doc.removeEventListener("pointerleave", this.leave);
|
|
1244
1343
|
this.view.removeEventListener("blur", this.blur);
|
|
1245
1344
|
this.view.removeEventListener("resize", this.refresh);
|
|
1246
|
-
this.doc.removeEventListener("scroll", this.
|
|
1345
|
+
this.doc.removeEventListener("scroll", this.scroll, true);
|
|
1247
1346
|
this.doc.removeEventListener("load", this.assetLoad, true);
|
|
1248
1347
|
this.doc.removeEventListener("loadeddata", this.assetLoad, true);
|
|
1249
1348
|
this.doc.removeEventListener("play", this.assetLoad, true);
|
|
@@ -1279,7 +1378,13 @@ var SceneRuntime = class {
|
|
|
1279
1378
|
}, `hover:${emitter.id}`, true)
|
|
1280
1379
|
}));
|
|
1281
1380
|
const sceneData = /* @__PURE__ */ new Map();
|
|
1282
|
-
const projections = batch.filter((entry) =>
|
|
1381
|
+
const projections = batch.filter((entry) => {
|
|
1382
|
+
if (!entry.visible || !entry.element.isConnected || entry.resuming && this.ambient.isPending(entry)) return false;
|
|
1383
|
+
const bounds = entry.bounds ??= entry.element.getBoundingClientRect();
|
|
1384
|
+
const visible = bounds.bottom > 0 && bounds.right > 0 && bounds.top < this.view.innerHeight && bounds.left < this.view.innerWidth;
|
|
1385
|
+
if (!visible) entry.resuming = true;
|
|
1386
|
+
return visible;
|
|
1387
|
+
}).map((entry) => {
|
|
1283
1388
|
entry.bounds ??= entry.element.getBoundingClientRect();
|
|
1284
1389
|
const origin = lightingOrigin(entry.element);
|
|
1285
1390
|
let nearest;
|
|
@@ -1298,13 +1403,17 @@ var SceneRuntime = class {
|
|
|
1298
1403
|
for (const { emitter, light } of activeLights) if (this.scope(emitter.element) === this.scope(entry.element) && visibility.layer(lightingOrigin(emitter.element)) === visibility.layer(origin) && !emitter.element.contains(entry.element) && (!entry.element.contains(emitter.element) || entry.element.matches("[role=\"menu\"], [role=\"tablist\"]"))) lights.push(light);
|
|
1299
1404
|
lights.push(...this.ambient.lights(entry));
|
|
1300
1405
|
const reflections = (data?.reflections ?? []).filter((reflection) => visibility.boundary(reflection.source) === boundary);
|
|
1301
|
-
|
|
1406
|
+
const lighting = this.project(entry, lights, reflections, visibility);
|
|
1407
|
+
lighting.immediate = entry.resuming || !entry.painted;
|
|
1408
|
+
entry.resuming = false;
|
|
1409
|
+
return [entry, lighting];
|
|
1302
1410
|
});
|
|
1303
1411
|
for (const entry of batch) this.queue.delete(entry);
|
|
1304
1412
|
for (const { emitter, color, exposed } of emissions) emitter.hooks.emit?.(exposed, color);
|
|
1305
1413
|
for (const [entry, lighting] of projections) {
|
|
1306
1414
|
if (this.sameLighting(entry.lastLighting, lighting)) continue;
|
|
1307
1415
|
entry.lastLighting = lighting;
|
|
1416
|
+
entry.painted = true;
|
|
1308
1417
|
const before = entry.element.getAttribute("style");
|
|
1309
1418
|
entry.hooks.light(lighting);
|
|
1310
1419
|
const after = entry.element.getAttribute("style");
|
|
@@ -1544,14 +1653,12 @@ function mountSurface(element, initial = {}) {
|
|
|
1544
1653
|
rim.className = "bx-glass-rim";
|
|
1545
1654
|
rim.setAttribute("aria-hidden", "true");
|
|
1546
1655
|
element.append(rim);
|
|
1547
|
-
const environment =
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
node.style.opacity = "0";
|
|
1551
|
-
rim.append(node);
|
|
1552
|
-
}
|
|
1656
|
+
const environment = doc.createElement("span");
|
|
1657
|
+
environment.className = "bx-glass-contribution bx-glass-environment";
|
|
1658
|
+
rim.append(environment);
|
|
1553
1659
|
let environmentImage = "none";
|
|
1554
|
-
|
|
1660
|
+
const environmentLayers = /* @__PURE__ */ new Map();
|
|
1661
|
+
const environmentColors = /* @__PURE__ */ new Map();
|
|
1555
1662
|
const ambient = doc.createElement("span");
|
|
1556
1663
|
ambient.className = "bx-glass-ambient";
|
|
1557
1664
|
decoration.append(light);
|
|
@@ -1703,16 +1810,30 @@ function mountSurface(element, initial = {}) {
|
|
|
1703
1810
|
element.style.setProperty("--bx-glass-lit-edge-bottom", edgeAt(50, 100));
|
|
1704
1811
|
element.style.setProperty("--bx-glass-lit-edge-left", edgeAt(0, 50));
|
|
1705
1812
|
}
|
|
1706
|
-
const
|
|
1813
|
+
const activeEnvironment = /* @__PURE__ */ new Set();
|
|
1814
|
+
for (const contribution of value.contributions) {
|
|
1815
|
+
if (!contribution.ambient) continue;
|
|
1816
|
+
const slot = Number(contribution.key.split(":").pop());
|
|
1817
|
+
if (!Number.isInteger(slot) || slot < 0 || slot >= 16) continue;
|
|
1818
|
+
activeEnvironment.add(slot);
|
|
1819
|
+
const property = `--bx-glass-environment-color-${slot}`;
|
|
1820
|
+
const color = `color-mix(in srgb, ${contribution.color} ${(contribution.edgeStrength * 100).toFixed(2)}%, transparent)`;
|
|
1821
|
+
if (environmentColors.get(slot) !== color) {
|
|
1822
|
+
environment.style.setProperty(property, color);
|
|
1823
|
+
environmentColors.set(slot, color);
|
|
1824
|
+
}
|
|
1825
|
+
environmentLayers.set(slot, `radial-gradient(circle ${contribution.spread}px at ${contribution.x.toFixed(2)}% ${contribution.y.toFixed(2)}%, var(${property}), transparent 75%)`);
|
|
1826
|
+
}
|
|
1827
|
+
for (const slot of environmentColors.keys()) if (!activeEnvironment.has(slot) && environmentColors.get(slot) !== "transparent") {
|
|
1828
|
+
environment.style.setProperty(`--bx-glass-environment-color-${slot}`, "transparent");
|
|
1829
|
+
environmentColors.set(slot, "transparent");
|
|
1830
|
+
}
|
|
1831
|
+
const ambientImage = [...environmentLayers.values()].join(", ") || "none";
|
|
1707
1832
|
if (ambientImage !== environmentImage) {
|
|
1708
1833
|
environmentImage = ambientImage;
|
|
1709
|
-
|
|
1710
|
-
environmentIndex = 1 - environmentIndex;
|
|
1711
|
-
const next = environment[environmentIndex];
|
|
1712
|
-
next.style.backgroundImage = ambientImage;
|
|
1713
|
-
next.style.opacity = "1";
|
|
1714
|
-
previous.style.opacity = "0";
|
|
1834
|
+
environment.style.backgroundImage = ambientImage;
|
|
1715
1835
|
}
|
|
1836
|
+
if (value.immediate || reducedMotion) for (const animation of environment.getAnimations()) animation.finish();
|
|
1716
1837
|
const contributions = value.contributions.filter((contribution) => !contribution.ambient);
|
|
1717
1838
|
const active = new Set(contributions.map((contribution) => contribution.key));
|
|
1718
1839
|
for (const contribution of contributions) setLayer(contribution);
|