nodality 1.0.195 → 1.0.196

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.
Files changed (168) hide show
  1. package/dist/animator.cjs.js +1 -1
  2. package/dist/animator.esm.js +1 -1
  3. package/dist/audionew.cjs.js +1 -1
  4. package/dist/audionew.esm.js +1 -1
  5. package/dist/beta-desktop-bar.cjs.js +1 -1
  6. package/dist/beta-desktop-bar.esm.js +1 -1
  7. package/dist/beta-mobile-bar.cjs.js +1 -1
  8. package/dist/beta-mobile-bar.esm.js +1 -1
  9. package/dist/bundle.umd.js +1 -1
  10. package/dist/button.cjs.js +1 -1
  11. package/dist/button.esm.js +1 -1
  12. package/dist/center.cjs.js +1 -1
  13. package/dist/center.esm.js +1 -1
  14. package/dist/checkbox.cjs.js +1 -1
  15. package/dist/checkbox.esm.js +1 -1
  16. package/dist/code.cjs.js +1 -1
  17. package/dist/code.esm.js +1 -1
  18. package/dist/container.cjs.js +1 -1
  19. package/dist/container.esm.js +1 -1
  20. package/dist/designer.cjs.js +1 -1
  21. package/dist/designer.esm.js +1 -1
  22. package/dist/dropdown.cjs.js +1 -1
  23. package/dist/dropdown.esm.js +1 -1
  24. package/dist/element-mapper.cjs.js +1 -1
  25. package/dist/element-mapper.esm.js +1 -1
  26. package/dist/finalresult.esm.js +1 -1
  27. package/dist/flex-card.cjs.js +1 -1
  28. package/dist/flex-card.esm.js +1 -1
  29. package/dist/flex-grid.cjs.js +1 -1
  30. package/dist/flex-grid.esm.js +1 -1
  31. package/dist/flex-row.cjs.js +1 -1
  32. package/dist/flex-row.esm.js +1 -1
  33. package/dist/floating-input.cjs.js +1 -1
  34. package/dist/floating-input.esm.js +1 -1
  35. package/dist/free.cjs.js +1 -1
  36. package/dist/free.esm.js +1 -1
  37. package/dist/image-picker.cjs.js +1 -1
  38. package/dist/image-picker.esm.js +1 -1
  39. package/dist/image.cjs.js +1 -1
  40. package/dist/image.esm.js +1 -1
  41. package/dist/index.cjs.js +1 -1
  42. package/dist/index.esm.js +1 -1
  43. package/dist/link-getter.cjs.js +1 -1
  44. package/dist/link-getter.esm.js +1 -1
  45. package/dist/link.cjs.js +1 -1
  46. package/dist/link.esm.js +1 -1
  47. package/dist/multiswitcher.cjs.js +1 -1
  48. package/dist/multiswitcher.esm.js +1 -1
  49. package/dist/new-nav-bar.cjs.js +1 -1
  50. package/dist/new-nav-bar.esm.js +1 -1
  51. package/dist/picker.cjs.js +1 -1
  52. package/dist/picker.esm.js +1 -1
  53. package/dist/side-nav-bar.cjs.js +1 -1
  54. package/dist/side-nav-bar.esm.js +1 -1
  55. package/dist/simple-bar.cjs.js +1 -1
  56. package/dist/simple-bar.esm.js +1 -1
  57. package/dist/slider-2025.cjs.js +1 -1
  58. package/dist/slider-2025.esm.js +1 -1
  59. package/dist/table.cjs.js +1 -1
  60. package/dist/table.esm.js +1 -1
  61. package/dist/text-field.cjs.js +1 -1
  62. package/dist/text-field.esm.js +1 -1
  63. package/dist/text.cjs.js +1 -1
  64. package/dist/text.esm.js +1 -1
  65. package/dist/ulist.cjs.js +1 -1
  66. package/dist/ulist.esm.js +1 -1
  67. package/dist/video.cjs.js +1 -1
  68. package/dist/video.esm.js +1 -1
  69. package/dist/zoom-card.cjs.js +1 -1
  70. package/dist/zoom-card.esm.js +1 -1
  71. package/layout/animator.js +1 -1
  72. package/layout/audio.js +1 -1
  73. package/layout/audionew.js +1 -1
  74. package/layout/base-2.js +1 -1
  75. package/layout/base.js +1 -1
  76. package/layout/beta-desktop-bar.js +1 -1
  77. package/layout/beta-mobile-bar.js +1 -1
  78. package/layout/box.js +1 -1
  79. package/layout/button.js +1 -1
  80. package/layout/cards.js +1 -1
  81. package/layout/center.js +1 -1
  82. package/layout/checkbox.js +1 -1
  83. package/layout/circle.js +1 -1
  84. package/layout/clean-row.js +1 -1
  85. package/layout/code.js +1 -1
  86. package/layout/container.js +1 -1
  87. package/layout/custom.js +1 -1
  88. package/layout/div-image.js +1 -1
  89. package/layout/dropdown-2025.js +1 -1
  90. package/layout/dropdown.js +1 -1
  91. package/layout/empty-element.js +1 -1
  92. package/layout/external-stylesheet.js +1 -1
  93. package/layout/flex-card.js +1 -1
  94. package/layout/flex-grid.js +1 -1
  95. package/layout/flex-row.js +1 -1
  96. package/layout/footer.js +1 -1
  97. package/layout/form-components/custom.js +1 -1
  98. package/layout/form-components/data-list.js +1 -1
  99. package/layout/form-components/floating-input.js +1 -1
  100. package/layout/form-components/form-all.js +1 -1
  101. package/layout/form-components/form.js +1 -1
  102. package/layout/form-components/image-picker.js +1 -1
  103. package/layout/form-components/picker.js +1 -1
  104. package/layout/form-components/radio.js +1 -1
  105. package/layout/form-components/radiogroup.js +1 -1
  106. package/layout/form-components/range.js +1 -1
  107. package/layout/free.js +1 -1
  108. package/layout/grid-new.js +1 -1
  109. package/layout/grid-switcher.js +1 -1
  110. package/layout/grid.js +1 -1
  111. package/layout/group.js +1 -1
  112. package/layout/header.js +1 -1
  113. package/layout/horizontal-scroller.js +1 -1
  114. package/layout/image-old.js +1 -1
  115. package/layout/image.js +1 -1
  116. package/layout/index.js +1 -1
  117. package/layout/label.js +1 -1
  118. package/layout/link.js +1 -1
  119. package/layout/list-OLD.js +1 -1
  120. package/layout/list.js +1 -1
  121. package/layout/meta-adder.js +1 -1
  122. package/layout/modal-2025.js +1 -1
  123. package/layout/modernwrap.js +1 -1
  124. package/layout/multiswitcher.js +1 -1
  125. package/layout/multiswitcherBeta.js +1 -1
  126. package/layout/nav-bar.js +1 -1
  127. package/layout/nav-factor/custom-div.js +1 -1
  128. package/layout/navBar-OLD.js +1 -1
  129. package/layout/new-flat-adder.js +1 -1
  130. package/layout/new-nav-bar.js +1 -1
  131. package/layout/offset-container.js +1 -1
  132. package/layout/polygon.js +1 -1
  133. package/layout/prerender-site.js +1 -1
  134. package/layout/prerender.js +1 -1
  135. package/layout/progress.js +1 -1
  136. package/layout/row.js +1 -1
  137. package/layout/saved-new-nav-bar.js +1 -1
  138. package/layout/scroll-video.js +1 -1
  139. package/layout/side-bar.js +1 -1
  140. package/layout/side-nav-bar.js +1 -1
  141. package/layout/simple-bar.js +1 -1
  142. package/layout/slider-2025.js +1 -1
  143. package/layout/spacer.js +1 -1
  144. package/layout/stack.js +1 -1
  145. package/layout/styler.js +1 -1
  146. package/layout/svg.js +1 -1
  147. package/layout/switcher.js +1 -1
  148. package/layout/table.js +1 -1
  149. package/layout/text-field.js +1 -1
  150. package/layout/text.js +1 -1
  151. package/layout/ulist.js +1 -1
  152. package/layout/video.js +1 -1
  153. package/layout/without-new.js +1 -1
  154. package/layout/wrap.js +1 -1
  155. package/layout/zoom-card.js +1 -1
  156. package/lib/card-getter.js +1 -1
  157. package/lib/data.js +1 -1
  158. package/lib/designer.js +1 -1
  159. package/lib/element-mapper.js +1 -1
  160. package/lib/keyframe-animation.js +1 -1
  161. package/lib/link-getter.js +1 -1
  162. package/lib/raster-ops.js +99 -14
  163. package/lib/scroll-video.js +1 -1
  164. package/lib/seo.js +1 -1
  165. package/lib/stacker.js +1 -1
  166. package/lib/theme.js +1 -1
  167. package/lib/transform-anim.js +1 -1
  168. package/package.json +1 -1
package/lib/raster-ops.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.195
2
+ * nodality v1.0.196
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -170,16 +170,17 @@ const REGISTRY = {
170
170
  // samples the finished field. See the `field` descriptor below and
171
171
  // the field-simulation block in applyRasterPipeline().
172
172
  //
173
- // Formulation (deliberately not the usual Stable-Fluids solver):
174
- // the classic GPU fluid pipeline is advect + vorticity confinement +
175
- // a divergence/pressure Jacobi solve (Stam 1999; Harris, GPU Gems
176
- // 2003) roughly ten passes. This op instead advects momentum along
177
- // its own flow (semi-Lagrangian backtrace, the one genuinely
178
- // universal piece) and then ROTATES each momentum vector by the
179
- // local curl angle. Rotation preserves magnitude, so eddies keep
180
- // spinning instead of being pushed around, and because it cannot
181
- // inject divergence energy the field stays stable with no pressure
182
- // projection at all the whole simulation is a single pass.
173
+ // Formulation: the classic GPU Stable-Fluids pipeline (Stam 1999;
174
+ // Harris, GPU Gems 2003) splat, curl, vorticity confinement,
175
+ // divergence, a Jacobi pressure solve, gradient subtraction, then
176
+ // semi-Lagrangian advection of velocity and dye. See the provenance
177
+ // note on the `stir` field descriptor below for the citations and
178
+ // for what this op inherits from existing implementations.
179
+ //
180
+ // An earlier version of this comment claimed the op was a single
181
+ // pass with no pressure projection. It never was the solver has
182
+ // always run the full projection, which is what makes the flow roll
183
+ // into persistent vortices rather than smear.
183
184
  //
184
185
  // { op: "stir", strength: 26, curl: 2.4, decay: 0.985 }
185
186
  //
@@ -544,8 +545,31 @@ void main() {
544
545
  // Stirred liquid: an incompressible fluid whose velocity field warps
545
546
  // the content and whose dye field colours it.
546
547
  //
547
- // Implemented from the published algorithm, not from any particular
548
- // existing codebase:
548
+ // Provenance. The solver was written from the published papers, and
549
+ // no code was copied from an existing implementation — the neighbour
550
+ // taps are computed in-fragment from gl_FragCoord rather than passed
551
+ // down as vL/vR/vT/vB varyings, advection samples directly instead of
552
+ // through a hand-rolled bilerp(), and the rainbow hue comes from the
553
+ // stroke direction rather than a random HSV pick. But it is not
554
+ // independent of that lineage either, and two things are inherited
555
+ // rather than derived from the papers:
556
+ //
557
+ // - The option vocabulary and several defaults (curl, pressure,
558
+ // pressureIterations, radius, force, intensity, rainbow,
559
+ // dyeResolution; resolution 128, dyeResolution 512, pressure 0.8)
560
+ // follow the conventions of Pavel Dobryakov's
561
+ // WebGL-Fluid-Simulation (MIT) and its many descendants.
562
+ // - The free-slip boundary handling — four inline conditionals in
563
+ // the divergence shader that mirror the centre velocity at the
564
+ // walls — is that codebase's approach. Stam and Harris both use a
565
+ // separate boundary pass over border geometry instead.
566
+ //
567
+ // Everything below that looks identical to other implementations
568
+ // beyond those two points is identical because the mathematics admits
569
+ // one spelling: (r+l+t+b-d)*0.25 is the Jacobi iteration as printed
570
+ // in GPU Gems 38, and the divergence, curl and confinement kernels
571
+ // are the standard central differences.
572
+ //
549
573
  // J. Stam, "Stable Fluids", SIGGRAPH '99, 121-128 - the
550
574
  // unconditionally stable operator splitting used here: add
551
575
  // forces, advect by a backward particle trace, then project the
@@ -1449,9 +1473,70 @@ function soleImageOf(el) {
1449
1473
  return img;
1450
1474
  }
1451
1475
 
1476
+ /**
1477
+ * Draw `img` into an offscreen canvas at the host's box, honouring the
1478
+ * element's own `object-fit` / `object-position`.
1479
+ *
1480
+ * The pipeline samples its texture as `fragCoord / u_res`, i.e. stretched
1481
+ * across the whole quad. That is right for a DOM snapshot, which is captured
1482
+ * at the canvas aspect — but the direct-image path uploads the source at its
1483
+ * NATURAL aspect, so any host whose box is a different shape rendered the
1484
+ * photo distorted, and `object-fit: cover` no longer had any say because the
1485
+ * image was no longer being laid out by CSS at all.
1486
+ *
1487
+ * Baking the fit in here keeps it out of the shader and means the texture
1488
+ * always arrives pre-cropped to the box the quad expects.
1489
+ */
1490
+ function fitImageToBox(img, w, h, dpr) {
1491
+ const cw = Math.max(1, Math.round(w * dpr));
1492
+ const ch = Math.max(1, Math.round(h * dpr));
1493
+ const iw = img.naturalWidth, ih = img.naturalHeight;
1494
+ if (!iw || !ih) return img;
1495
+
1496
+ let fit = "fill", pos = "50% 50%";
1497
+ if (typeof getComputedStyle === "function") {
1498
+ const cs = getComputedStyle(img);
1499
+ fit = cs.objectFit || "fill";
1500
+ pos = cs.objectPosition || "50% 50%";
1501
+ }
1502
+ // `fill` is the CSS default and matches the old stretch behaviour, so
1503
+ // leave those callers on the cheap path.
1504
+ if (fit === "fill") return img;
1505
+
1506
+ const sx = cw / iw, sy = ch / ih;
1507
+ const scale = fit === "cover" ? Math.max(sx, sy)
1508
+ : fit === "contain" ? Math.min(sx, sy)
1509
+ : fit === "none" ? 1
1510
+ : fit === "scale-down" ? Math.min(1, Math.min(sx, sy))
1511
+ : Math.max(sx, sy);
1512
+
1513
+ const dw = iw * scale, dh = ih * scale;
1514
+ // object-position: percentages position the overflow, so 0% pins the
1515
+ // near edge and 100% the far edge.
1516
+ const parts = String(pos).trim().split(/\s+/);
1517
+ const frac = (v, i) => {
1518
+ if (v == null) return 0.5;
1519
+ if (v.endsWith("%")) return parseFloat(v) / 100;
1520
+ if (v === "left" || v === "top") return 0;
1521
+ if (v === "right" || v === "bottom") return 1;
1522
+ if (v === "center") return 0.5;
1523
+ const px = parseFloat(v);
1524
+ return isNaN(px) ? 0.5 : px / (i === 0 ? Math.max(cw - dw, 1) : Math.max(ch - dh, 1));
1525
+ };
1526
+ const fx = frac(parts[0], 0);
1527
+ const fy = frac(parts.length > 1 ? parts[1] : parts[0], 1);
1528
+
1529
+ const c = document.createElement("canvas");
1530
+ c.width = cw; c.height = ch;
1531
+ const ctx = c.getContext("2d");
1532
+ if (!ctx) return img;
1533
+ ctx.drawImage(img, (cw - dw) * fx, (ch - dh) * fy, dw, dh);
1534
+ return c;
1535
+ }
1536
+
1452
1537
  function snapshotToImage(el, w, h, dpr) {
1453
1538
  const direct = soleImageOf(el);
1454
- if (direct) return Promise.resolve(direct);
1539
+ if (direct) return Promise.resolve(fitImageToBox(direct, w, h, dpr));
1455
1540
 
1456
1541
  return new Promise((resolve, reject) => {
1457
1542
  const serialized = new XMLSerializer()
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.195
2
+ * nodality v1.0.196
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/seo.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.195
2
+ * nodality v1.0.196
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/stacker.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.195
2
+ * nodality v1.0.196
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/theme.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.195
2
+ * nodality v1.0.196
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.195
2
+ * nodality v1.0.196
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodality",
3
- "version": "1.0.195",
3
+ "version": "1.0.196",
4
4
  "description": "A lightweight library for declarative UI elements.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",