nodality 1.0.186 → 1.0.187
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/animator.cjs.js +1 -1
- package/dist/animator.esm.js +1 -1
- package/dist/audionew.cjs.js +1 -1
- package/dist/audionew.esm.js +1 -1
- package/dist/beta-desktop-bar.cjs.js +1 -1
- package/dist/beta-desktop-bar.esm.js +1 -1
- package/dist/beta-mobile-bar.cjs.js +1 -1
- package/dist/beta-mobile-bar.esm.js +1 -1
- package/dist/bundle.umd.js +1 -1
- package/dist/button.cjs.js +1 -1
- package/dist/button.esm.js +1 -1
- package/dist/center.cjs.js +1 -1
- package/dist/center.esm.js +1 -1
- package/dist/checkbox.cjs.js +1 -1
- package/dist/checkbox.esm.js +1 -1
- package/dist/code.cjs.js +1 -1
- package/dist/code.esm.js +1 -1
- package/dist/container.cjs.js +1 -1
- package/dist/container.esm.js +1 -1
- package/dist/designer.cjs.js +1 -1
- package/dist/designer.esm.js +1 -1
- package/dist/dropdown.cjs.js +1 -1
- package/dist/dropdown.esm.js +1 -1
- package/dist/element-mapper.cjs.js +1 -1
- package/dist/element-mapper.esm.js +1 -1
- package/dist/finalresult.esm.js +1 -1
- package/dist/flex-card.cjs.js +1 -1
- package/dist/flex-card.esm.js +1 -1
- package/dist/flex-grid.cjs.js +1 -1
- package/dist/flex-grid.esm.js +1 -1
- package/dist/flex-row.cjs.js +1 -1
- package/dist/flex-row.esm.js +1 -1
- package/dist/floating-input.cjs.js +1 -1
- package/dist/floating-input.esm.js +1 -1
- package/dist/free.cjs.js +1 -1
- package/dist/free.esm.js +1 -1
- package/dist/image-picker.cjs.js +1 -1
- package/dist/image-picker.esm.js +1 -1
- package/dist/image.cjs.js +1 -1
- package/dist/image.esm.js +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/link-getter.cjs.js +1 -1
- package/dist/link-getter.esm.js +1 -1
- package/dist/link.cjs.js +1 -1
- package/dist/link.esm.js +1 -1
- package/dist/multiswitcher.cjs.js +1 -1
- package/dist/multiswitcher.esm.js +1 -1
- package/dist/new-nav-bar.cjs.js +1 -1
- package/dist/new-nav-bar.esm.js +1 -1
- package/dist/picker.cjs.js +1 -1
- package/dist/picker.esm.js +1 -1
- package/dist/side-nav-bar.cjs.js +1 -1
- package/dist/side-nav-bar.esm.js +1 -1
- package/dist/simple-bar.cjs.js +1 -1
- package/dist/simple-bar.esm.js +1 -1
- package/dist/slider-2025.cjs.js +1 -1
- package/dist/slider-2025.esm.js +1 -1
- package/dist/table.cjs.js +1 -1
- package/dist/table.esm.js +1 -1
- package/dist/text-field.cjs.js +1 -1
- package/dist/text-field.esm.js +1 -1
- package/dist/text.cjs.js +1 -1
- package/dist/text.esm.js +1 -1
- package/dist/ulist.cjs.js +1 -1
- package/dist/ulist.esm.js +1 -1
- package/dist/video.cjs.js +1 -1
- package/dist/video.esm.js +1 -1
- package/dist/zoom-card.cjs.js +1 -1
- package/dist/zoom-card.esm.js +1 -1
- package/layout/animator.js +1 -1
- package/layout/audio.js +1 -1
- package/layout/audionew.js +1 -1
- package/layout/base-2.js +1 -1
- package/layout/base.js +1 -1
- package/layout/beta-desktop-bar.js +1 -1
- package/layout/beta-mobile-bar.js +1 -1
- package/layout/box.js +1 -1
- package/layout/button.js +1 -1
- package/layout/cards.js +1 -1
- package/layout/center.js +1 -1
- package/layout/checkbox.js +1 -1
- package/layout/circle.js +1 -1
- package/layout/clean-row.js +1 -1
- package/layout/code.js +1 -1
- package/layout/container.js +1 -1
- package/layout/custom.js +1 -1
- package/layout/div-image.js +1 -1
- package/layout/dropdown-2025.js +1 -1
- package/layout/dropdown.js +1 -1
- package/layout/empty-element.js +1 -1
- package/layout/external-stylesheet.js +1 -1
- package/layout/flex-card.js +1 -1
- package/layout/flex-grid.js +1 -1
- package/layout/flex-row.js +1 -1
- package/layout/footer.js +1 -1
- package/layout/form-components/custom.js +1 -1
- package/layout/form-components/data-list.js +1 -1
- package/layout/form-components/floating-input.js +1 -1
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +1 -1
- package/layout/form-components/picker.js +1 -1
- package/layout/form-components/radio.js +1 -1
- package/layout/form-components/radiogroup.js +1 -1
- package/layout/form-components/range.js +1 -1
- package/layout/free.js +1 -1
- package/layout/grid-new.js +1 -1
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/group.js +1 -1
- package/layout/header.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image-old.js +1 -1
- package/layout/image.js +1 -1
- package/layout/index.js +1 -1
- package/layout/label.js +1 -1
- package/layout/link.js +1 -1
- package/layout/list-OLD.js +1 -1
- package/layout/list.js +1 -1
- package/layout/meta-adder.js +1 -1
- package/layout/modal-2025.js +1 -1
- package/layout/modernwrap.js +1 -1
- package/layout/multiswitcher.js +1 -1
- package/layout/multiswitcherBeta.js +1 -1
- package/layout/nav-bar.js +1 -1
- package/layout/nav-factor/custom-div.js +1 -1
- package/layout/navBar-OLD.js +1 -1
- package/layout/new-flat-adder.js +1 -1
- package/layout/new-nav-bar.js +1 -1
- package/layout/offset-container.js +1 -1
- package/layout/polygon.js +1 -1
- package/layout/prerender-site.js +1 -1
- package/layout/prerender.js +1 -1
- package/layout/progress.js +1 -1
- package/layout/row.js +1 -1
- package/layout/saved-new-nav-bar.js +1 -1
- package/layout/scroll-video.js +1 -1
- package/layout/side-bar.js +1 -1
- package/layout/side-nav-bar.js +1 -1
- package/layout/simple-bar.js +1 -1
- package/layout/slider-2025.js +1 -1
- package/layout/spacer.js +1 -1
- package/layout/stack.js +1 -1
- package/layout/styler.js +1 -1
- package/layout/svg.js +1 -1
- package/layout/switcher.js +1 -1
- package/layout/table.js +1 -1
- package/layout/text-field.js +1 -1
- package/layout/text.js +1 -1
- package/layout/ulist.js +1 -1
- package/layout/video.js +1 -1
- package/layout/without-new.js +1 -1
- package/layout/wrap.js +1 -1
- package/layout/zoom-card.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +1 -1
- package/lib/element-mapper.js +1 -1
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/raster-ops.js +121 -13
- package/lib/scroll-video.js +1 -1
- package/lib/seo.js +1 -1
- package/lib/stacker.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- package/package.json +1 -1
package/lib/raster-ops.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.0.
|
|
2
|
+
* nodality v1.0.187
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -955,9 +955,38 @@ ${defaultSeam}
|
|
|
955
955
|
|
|
956
956
|
// ── Snapshot backend: DOM subtree -> SVG foreignObject -> texture ────
|
|
957
957
|
|
|
958
|
+
// Viewport-relative CSS inside a foreignObject resolves against the SVG
|
|
959
|
+
// element's own size, not the browser viewport — so `font-size: calc(
|
|
960
|
+
// 1.625rem + 5.075vw)` renders at a different size in the snapshot than
|
|
961
|
+
// it does on the page. The glyphs then sit somewhere the DOM text does
|
|
962
|
+
// not, which is what makes the selection highlight look offset.
|
|
963
|
+
//
|
|
964
|
+
// Freeze those declarations to the pixel values the element actually
|
|
965
|
+
// computes, on a clone, so the snapshot matches the live layout.
|
|
966
|
+
const VIEWPORT_UNIT = /\d(?:vw|vh|vmin|vmax|dvw|dvh|svw|svh|lvw|lvh)\b/i;
|
|
967
|
+
|
|
968
|
+
function freezeViewportUnits(original, clone) {
|
|
969
|
+
const origs = [original, ...original.querySelectorAll("*")];
|
|
970
|
+
const clones = [clone, ...clone.querySelectorAll("*")];
|
|
971
|
+
for (let i = 0; i < origs.length && i < clones.length; i++) {
|
|
972
|
+
const inline = clones[i].style;
|
|
973
|
+
if (!inline || inline.length === 0) continue;
|
|
974
|
+
let computed = null;
|
|
975
|
+
// Iterate a snapshot of the names: writing to style mutates the list.
|
|
976
|
+
for (const prop of Array.from(inline)) {
|
|
977
|
+
if (!VIEWPORT_UNIT.test(inline.getPropertyValue(prop))) continue;
|
|
978
|
+
computed = computed || window.getComputedStyle(origs[i]);
|
|
979
|
+
const px = computed.getPropertyValue(prop);
|
|
980
|
+
if (px) inline.setProperty(prop, px, inline.getPropertyPriority(prop));
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return clone;
|
|
984
|
+
}
|
|
985
|
+
|
|
958
986
|
function snapshotToImage(el, w, h, dpr) {
|
|
959
987
|
return new Promise((resolve, reject) => {
|
|
960
|
-
const serialized = new XMLSerializer()
|
|
988
|
+
const serialized = new XMLSerializer()
|
|
989
|
+
.serializeToString(freezeViewportUnits(el, el.cloneNode(true)));
|
|
961
990
|
const svg =
|
|
962
991
|
`<svg xmlns="http://www.w3.org/2000/svg" width="${w * dpr}" height="${h * dpr}" viewBox="0 0 ${w} ${h}">` +
|
|
963
992
|
`<foreignObject width="100%" height="100%">` +
|
|
@@ -1067,6 +1096,16 @@ function applyRasterPipeline(el, rasterNodes) {
|
|
|
1067
1096
|
// chrome://flags/#canvas-draw-element). layoutsubtree was already
|
|
1068
1097
|
// set before context creation above.
|
|
1069
1098
|
const wrap = document.createElement("div");
|
|
1099
|
+
// The wrapper MUST fill the canvas box. Left to itself it
|
|
1100
|
+
// shrink-wraps its content — a headline wraps to the text width,
|
|
1101
|
+
// not the element width — and texElementImage2D then captures
|
|
1102
|
+
// that narrower box while the shader maps the texture across the
|
|
1103
|
+
// whole canvas. Everything comes out stretched horizontally by
|
|
1104
|
+
// canvasWidth/contentWidth, so the drawn glyphs no longer sit
|
|
1105
|
+
// where the DOM text does and selection lands on the wrong
|
|
1106
|
+
// characters.
|
|
1107
|
+
wrap.style.cssText =
|
|
1108
|
+
`display:block;width:${rect.width}px;height:${rect.height}px;`;
|
|
1070
1109
|
while (el.firstChild) wrap.appendChild(el.firstChild);
|
|
1071
1110
|
canvas.appendChild(wrap);
|
|
1072
1111
|
sourceEl = wrap;
|
|
@@ -1075,13 +1114,24 @@ function applyRasterPipeline(el, rasterNodes) {
|
|
|
1075
1114
|
canvas.style.cssText =
|
|
1076
1115
|
`display:block;width:${rect.width}px;height:${rect.height}px;`;
|
|
1077
1116
|
} else {
|
|
1078
|
-
// Snapshot mode: purely visual overlay
|
|
1079
|
-
// underneath for accessibility, selection and events.
|
|
1117
|
+
// Snapshot mode: purely visual overlay.
|
|
1080
1118
|
canvas.style.cssText =
|
|
1081
1119
|
"position:absolute;top:0;left:0;" +
|
|
1082
1120
|
`width:${rect.width}px;height:${rect.height}px;` +
|
|
1083
1121
|
"pointer-events:none;z-index:2147483000;";
|
|
1084
|
-
|
|
1122
|
+
if (pureOverlay) {
|
|
1123
|
+
// The real content is still visible underneath and keeps its
|
|
1124
|
+
// own semantics, so the canvas is pure decoration.
|
|
1125
|
+
canvas.setAttribute("aria-hidden", "true");
|
|
1126
|
+
} else {
|
|
1127
|
+
// In-place: the host gets hidden below, which would take its
|
|
1128
|
+
// text out of the accessibility tree, out of find-in-page and
|
|
1129
|
+
// out of innerText. Carry the label onto the canvas so the
|
|
1130
|
+
// element is still announced rather than silently vanishing.
|
|
1131
|
+
canvas.setAttribute("role", "img");
|
|
1132
|
+
const label = (el.textContent || "").replace(/\s+/g, " ").trim();
|
|
1133
|
+
if (label) canvas.setAttribute("aria-label", label.slice(0, 300));
|
|
1134
|
+
}
|
|
1085
1135
|
}
|
|
1086
1136
|
el.appendChild(canvas);
|
|
1087
1137
|
|
|
@@ -1335,6 +1385,65 @@ function applyRasterPipeline(el, rasterNodes) {
|
|
|
1335
1385
|
// texture is live, the host's own painting is hidden via the
|
|
1336
1386
|
// visibility trick (the canvas child re-shows itself) so transparent
|
|
1337
1387
|
// hosts — e.g. a bare headline — don't ghost-double under the effect.
|
|
1388
|
+
// Keeping the host selectable.
|
|
1389
|
+
// --------------------------------------------------------------
|
|
1390
|
+
// The host must NOT be visibility:hidden. Hidden text cannot be
|
|
1391
|
+
// selected, so dragging over the effect either selects nothing or
|
|
1392
|
+
// catches neighbouring content — which is what makes the highlight
|
|
1393
|
+
// look offset and unreliable. Instead the host stays in the flow
|
|
1394
|
+
// with its ink made transparent, and the canvas is painted BEHIND
|
|
1395
|
+
// it. The glyphs are invisible but still hit-testable, and the
|
|
1396
|
+
// browser paints the selection highlight above the canvas, aligned
|
|
1397
|
+
// with the real text, because that is where the text actually is.
|
|
1398
|
+
const INK = {
|
|
1399
|
+
"color": "transparent",
|
|
1400
|
+
"-webkit-text-fill-color": "transparent",
|
|
1401
|
+
"-webkit-text-stroke-color": "transparent",
|
|
1402
|
+
"background-color": "transparent",
|
|
1403
|
+
"background-image": "none",
|
|
1404
|
+
"border-color": "transparent",
|
|
1405
|
+
"box-shadow": "none",
|
|
1406
|
+
"text-shadow": "none",
|
|
1407
|
+
};
|
|
1408
|
+
const REPLACED = "img,svg,video,picture,iframe";
|
|
1409
|
+
let inkSaved = null;
|
|
1410
|
+
|
|
1411
|
+
const hideHostInk = () => {
|
|
1412
|
+
if (inkSaved) return;
|
|
1413
|
+
inkSaved = [];
|
|
1414
|
+
for (const node of [el, ...el.querySelectorAll("*")]) {
|
|
1415
|
+
if (node === canvas || node.tagName === "CANVAS") continue;
|
|
1416
|
+
const saved = { op: node.style.getPropertyValue("opacity") };
|
|
1417
|
+
for (const p in INK) saved[p] = node.style.getPropertyValue(p);
|
|
1418
|
+
inkSaved.push([node, saved]);
|
|
1419
|
+
for (const p in INK) node.style.setProperty(p, INK[p], "important");
|
|
1420
|
+
// Replaced content has no "ink" property to neutralise.
|
|
1421
|
+
if (node !== el && node.matches && node.matches(REPLACED)) {
|
|
1422
|
+
node.style.setProperty("opacity", "0", "important");
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
// Contain the negative-z canvas so it stays behind this element's
|
|
1426
|
+
// text but never slips behind an ancestor's background.
|
|
1427
|
+
el.style.isolation = "isolate";
|
|
1428
|
+
canvas.style.zIndex = "-1";
|
|
1429
|
+
};
|
|
1430
|
+
|
|
1431
|
+
const showHostInk = () => {
|
|
1432
|
+
el.style.visibility = "";
|
|
1433
|
+
if (!inkSaved) return;
|
|
1434
|
+
for (const [node, saved] of inkSaved) {
|
|
1435
|
+
for (const p in INK) {
|
|
1436
|
+
if (saved[p]) node.style.setProperty(p, saved[p]);
|
|
1437
|
+
else node.style.removeProperty(p);
|
|
1438
|
+
}
|
|
1439
|
+
if (saved.op) node.style.setProperty("opacity", saved.op);
|
|
1440
|
+
else node.style.removeProperty("opacity");
|
|
1441
|
+
}
|
|
1442
|
+
inkSaved = null;
|
|
1443
|
+
el.style.isolation = "";
|
|
1444
|
+
canvas.style.zIndex = "";
|
|
1445
|
+
};
|
|
1446
|
+
|
|
1338
1447
|
const snapshotCapture = () => {
|
|
1339
1448
|
// Overlay + image content: use the image directly as the texture.
|
|
1340
1449
|
if (isOverlay) {
|
|
@@ -1359,8 +1468,7 @@ function applyRasterPipeline(el, rasterNodes) {
|
|
|
1359
1468
|
}
|
|
1360
1469
|
}
|
|
1361
1470
|
canvas.style.display = "none";
|
|
1362
|
-
|
|
1363
|
-
el.style.visibility = "";
|
|
1471
|
+
showHostInk();
|
|
1364
1472
|
const p = snapshotToImage(el, rect.width, rect.height, dpr)
|
|
1365
1473
|
.then((img) => {
|
|
1366
1474
|
if (destroyed) return;
|
|
@@ -1368,15 +1476,14 @@ function applyRasterPipeline(el, rasterNodes) {
|
|
|
1368
1476
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
|
|
1369
1477
|
finishUpload();
|
|
1370
1478
|
textureReady = true;
|
|
1371
|
-
//
|
|
1372
|
-
//
|
|
1373
|
-
//
|
|
1374
|
-
|
|
1375
|
-
el.style.visibility = pureOverlay ? "" : "hidden";
|
|
1479
|
+
// A pure-overlay chain leaves the host alone; the lens
|
|
1480
|
+
// floats over untouched content. Otherwise the canvas
|
|
1481
|
+
// carries the look and the host's own ink is suppressed.
|
|
1482
|
+
if (!pureOverlay) hideHostInk();
|
|
1376
1483
|
canvas.style.visibility = "visible";
|
|
1377
1484
|
})
|
|
1378
1485
|
.catch((e) => {
|
|
1379
|
-
|
|
1486
|
+
showHostInk();
|
|
1380
1487
|
console.warn("[nodality] raster snapshot failed:", e);
|
|
1381
1488
|
});
|
|
1382
1489
|
canvas.style.display = "";
|
|
@@ -1671,6 +1778,7 @@ function applyRasterPipeline(el, rasterNodes) {
|
|
|
1671
1778
|
}
|
|
1672
1779
|
solverOps.length = 0;
|
|
1673
1780
|
while (sourceEl !== el && sourceEl.firstChild) el.appendChild(sourceEl.firstChild);
|
|
1781
|
+
showHostInk();
|
|
1674
1782
|
el.style.visibility = "";
|
|
1675
1783
|
canvas.remove();
|
|
1676
1784
|
},
|
package/lib/scroll-video.js
CHANGED
package/lib/seo.js
CHANGED
package/lib/stacker.js
CHANGED
package/lib/theme.js
CHANGED
package/lib/transform-anim.js
CHANGED