nodality 1.0.196 → 1.0.198

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 (192) 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/base.cjs.js +1 -1
  6. package/dist/base.esm.js +1 -1
  7. package/dist/beta-desktop-bar.cjs.js +1 -1
  8. package/dist/beta-desktop-bar.esm.js +1 -1
  9. package/dist/beta-mobile-bar.cjs.js +1 -1
  10. package/dist/beta-mobile-bar.esm.js +1 -1
  11. package/dist/bundle.umd.js +1 -1
  12. package/dist/button.cjs.js +1 -1
  13. package/dist/button.esm.js +1 -1
  14. package/dist/center.cjs.js +1 -1
  15. package/dist/center.esm.js +1 -1
  16. package/dist/checkbox.cjs.js +1 -1
  17. package/dist/checkbox.esm.js +1 -1
  18. package/dist/code.cjs.js +1 -1
  19. package/dist/code.esm.js +1 -1
  20. package/dist/container.cjs.js +1 -1
  21. package/dist/container.esm.js +1 -1
  22. package/dist/data-list.cjs.js +1 -1
  23. package/dist/data-list.esm.js +1 -1
  24. package/dist/designer.cjs.js +1 -1
  25. package/dist/designer.esm.js +1 -1
  26. package/dist/dropdown.cjs.js +1 -1
  27. package/dist/dropdown.esm.js +1 -1
  28. package/dist/element-mapper.cjs.js +1 -1
  29. package/dist/element-mapper.esm.js +1 -1
  30. package/dist/finalresult.esm.js +1 -1
  31. package/dist/flex-card.cjs.js +1 -1
  32. package/dist/flex-card.esm.js +1 -1
  33. package/dist/flex-grid.cjs.js +1 -1
  34. package/dist/flex-grid.esm.js +1 -1
  35. package/dist/flex-row.cjs.js +1 -1
  36. package/dist/flex-row.esm.js +1 -1
  37. package/dist/floating-input.cjs.js +1 -1
  38. package/dist/floating-input.esm.js +1 -1
  39. package/dist/free.cjs.js +1 -1
  40. package/dist/free.esm.js +1 -1
  41. package/dist/horizontal-scroller.cjs.js +1 -1
  42. package/dist/horizontal-scroller.esm.js +1 -1
  43. package/dist/image-picker.cjs.js +1 -1
  44. package/dist/image-picker.esm.js +1 -1
  45. package/dist/image.cjs.js +1 -1
  46. package/dist/image.esm.js +1 -1
  47. package/dist/index.cjs.js +1 -1
  48. package/dist/index.esm.js +1 -1
  49. package/dist/link-getter.cjs.js +1 -1
  50. package/dist/link-getter.esm.js +1 -1
  51. package/dist/link.cjs.js +1 -1
  52. package/dist/link.esm.js +1 -1
  53. package/dist/meta-adder.cjs.js +1 -1
  54. package/dist/meta-adder.esm.js +1 -1
  55. package/dist/modal-2025.cjs.js +1 -1
  56. package/dist/modal-2025.esm.js +1 -1
  57. package/dist/multiswitcher.cjs.js +1 -1
  58. package/dist/multiswitcher.esm.js +1 -1
  59. package/dist/new-nav-bar.cjs.js +1 -1
  60. package/dist/new-nav-bar.esm.js +1 -1
  61. package/dist/picker.cjs.js +1 -1
  62. package/dist/picker.esm.js +1 -1
  63. package/dist/progress.cjs.js +1 -1
  64. package/dist/progress.esm.js +1 -1
  65. package/dist/radio.cjs.js +1 -1
  66. package/dist/radio.esm.js +1 -1
  67. package/dist/range.cjs.js +1 -1
  68. package/dist/range.esm.js +1 -1
  69. package/dist/side-bar.cjs.js +1 -1
  70. package/dist/side-bar.esm.js +1 -1
  71. package/dist/side-nav-bar.cjs.js +1 -1
  72. package/dist/side-nav-bar.esm.js +1 -1
  73. package/dist/simple-bar.cjs.js +1 -1
  74. package/dist/simple-bar.esm.js +1 -1
  75. package/dist/slider-2025.cjs.js +1 -1
  76. package/dist/slider-2025.esm.js +1 -1
  77. package/dist/spacer.cjs.js +1 -1
  78. package/dist/spacer.esm.js +1 -1
  79. package/dist/stack.cjs.js +1 -1
  80. package/dist/stack.esm.js +1 -1
  81. package/dist/table.cjs.js +1 -1
  82. package/dist/table.esm.js +1 -1
  83. package/dist/text-field.cjs.js +1 -1
  84. package/dist/text-field.esm.js +1 -1
  85. package/dist/text.cjs.js +1 -1
  86. package/dist/text.esm.js +1 -1
  87. package/dist/ulist.cjs.js +1 -1
  88. package/dist/ulist.esm.js +1 -1
  89. package/dist/video.cjs.js +1 -1
  90. package/dist/video.esm.js +1 -1
  91. package/dist/wrap.cjs.js +1 -1
  92. package/dist/wrap.esm.js +1 -1
  93. package/dist/zoom-card.cjs.js +1 -1
  94. package/dist/zoom-card.esm.js +1 -1
  95. package/layout/animator.js +1 -1
  96. package/layout/audio.js +1 -1
  97. package/layout/audionew.js +1 -1
  98. package/layout/base-2.js +1 -1
  99. package/layout/base.js +1 -1
  100. package/layout/beta-desktop-bar.js +1 -1
  101. package/layout/beta-mobile-bar.js +1 -1
  102. package/layout/box.js +1 -1
  103. package/layout/button.js +1 -1
  104. package/layout/cards.js +1 -1
  105. package/layout/center.js +1 -1
  106. package/layout/checkbox.js +1 -1
  107. package/layout/circle.js +1 -1
  108. package/layout/clean-row.js +1 -1
  109. package/layout/code.js +1 -1
  110. package/layout/container.js +1 -1
  111. package/layout/custom.js +1 -1
  112. package/layout/div-image.js +1 -1
  113. package/layout/dropdown-2025.js +1 -1
  114. package/layout/dropdown.js +1 -1
  115. package/layout/empty-element.js +1 -1
  116. package/layout/external-stylesheet.js +1 -1
  117. package/layout/flex-card.js +1 -1
  118. package/layout/flex-grid.js +1 -1
  119. package/layout/flex-row.js +1 -1
  120. package/layout/footer.js +1 -1
  121. package/layout/form-components/custom.js +1 -1
  122. package/layout/form-components/data-list.js +1 -1
  123. package/layout/form-components/floating-input.js +1 -1
  124. package/layout/form-components/form-all.js +1 -1
  125. package/layout/form-components/form.js +1 -1
  126. package/layout/form-components/image-picker.js +1 -1
  127. package/layout/form-components/picker.js +1 -1
  128. package/layout/form-components/radio.js +1 -1
  129. package/layout/form-components/radiogroup.js +1 -1
  130. package/layout/form-components/range.js +1 -1
  131. package/layout/free.js +1 -1
  132. package/layout/grid-new.js +1 -1
  133. package/layout/grid-switcher.js +1 -1
  134. package/layout/grid.js +1 -1
  135. package/layout/group.js +1 -1
  136. package/layout/header.js +1 -1
  137. package/layout/horizontal-scroller.js +1 -1
  138. package/layout/image-old.js +1 -1
  139. package/layout/image.js +1 -1
  140. package/layout/index.js +1 -1
  141. package/layout/label.js +1 -1
  142. package/layout/link.js +1 -1
  143. package/layout/list-OLD.js +1 -1
  144. package/layout/list.js +1 -1
  145. package/layout/meta-adder.js +1 -1
  146. package/layout/modal-2025.js +1 -1
  147. package/layout/modernwrap.js +1 -1
  148. package/layout/multiswitcher.js +1 -1
  149. package/layout/multiswitcherBeta.js +1 -1
  150. package/layout/nav-bar.js +1 -1
  151. package/layout/nav-factor/custom-div.js +1 -1
  152. package/layout/navBar-OLD.js +1 -1
  153. package/layout/new-flat-adder.js +1 -1
  154. package/layout/new-nav-bar.js +28 -2
  155. package/layout/offset-container.js +1 -1
  156. package/layout/polygon.js +1 -1
  157. package/layout/prerender-site.js +1 -1
  158. package/layout/prerender.js +1 -1
  159. package/layout/progress.js +1 -1
  160. package/layout/row.js +1 -1
  161. package/layout/saved-new-nav-bar.js +1 -1
  162. package/layout/scroll-video.js +1 -1
  163. package/layout/side-bar.js +1 -1
  164. package/layout/side-nav-bar.js +1 -1
  165. package/layout/simple-bar.js +1 -1
  166. package/layout/slider-2025.js +1 -1
  167. package/layout/spacer.js +1 -1
  168. package/layout/stack.js +1 -1
  169. package/layout/styler.js +1 -1
  170. package/layout/svg.js +1 -1
  171. package/layout/switcher.js +1 -1
  172. package/layout/table.js +1 -1
  173. package/layout/text-field.js +1 -1
  174. package/layout/text.js +1 -1
  175. package/layout/ulist.js +1 -1
  176. package/layout/video.js +1 -1
  177. package/layout/without-new.js +1 -1
  178. package/layout/wrap.js +1 -1
  179. package/layout/zoom-card.js +1 -1
  180. package/lib/card-getter.js +1 -1
  181. package/lib/data.js +1 -1
  182. package/lib/designer.js +1 -1
  183. package/lib/element-mapper.js +1 -1
  184. package/lib/keyframe-animation.js +1 -1
  185. package/lib/link-getter.js +1 -1
  186. package/lib/raster-ops.js +162 -5
  187. package/lib/scroll-video.js +1 -1
  188. package/lib/seo.js +1 -1
  189. package/lib/stacker.js +1 -1
  190. package/lib/theme.js +1 -1
  191. package/lib/transform-anim.js +1 -1
  192. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/data.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/designer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/raster-ops.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -79,8 +79,17 @@ const DRIVER_NAMES = Object.keys(DRIVERS);
79
79
  const REGISTRY = {
80
80
  hexalize: {
81
81
  stage: "cell",
82
- decl: (p) => `uniform float ${p}size;`,
83
- code: (p) => `
82
+ decl: (p) => `
83
+ uniform float ${p}size;
84
+ uniform float ${p}lift;
85
+ uniform float ${p}radius;
86
+ uniform vec2 ${p}dpos;
87
+ uniform float ${p}damt;`,
88
+ code: (p, node) => {
89
+ // Without `lift` this is the original cheap path: find the
90
+ // owning cell, draw its border, done.
91
+ if (!node.lift) {
92
+ return `
84
93
  {
85
94
  vec2 hp = warped / ${p}size;
86
95
  vec2 hr = vec2(1.0, 1.7320508), hh = hr * 0.5;
@@ -90,8 +99,88 @@ const REGISTRY = {
90
99
  gv = abs(gv);
91
100
  edge = max(edge, smoothstep(0.44, 0.5,
92
101
  max(dot(gv, normalize(vec2(1.0, 1.7320508))), gv.x)));
93
- }`,
94
- uniforms: (node, dpr) => ({ size: ["1f", (node.size || 24) * dpr] }),
102
+ }`;
103
+ }
104
+
105
+ // With `lift`, cells near the pointer come TOWARD the viewer.
106
+ //
107
+ // A grown hexagon covers ground outside its own lattice cell,
108
+ // so a fragment can no longer assume it belongs to the cell it
109
+ // sits in — the neighbour may have swollen over it. Testing
110
+ // only the owning cell is what made the first two attempts
111
+ // fail: the border simply left the cell and vanished, because
112
+ // nothing ever drew the part that hung over its neighbours.
113
+ //
114
+ // So each fragment tests its own cell AND the six around it,
115
+ // and takes the most-enlarged hexagon that covers it. Largest
116
+ // scale wins, which is the same as "nearest to the viewer" —
117
+ // that is what makes them overlap correctly instead of
118
+ // fighting. Six neighbours is enough for any scale under 2x.
119
+ const NB = [
120
+ [1, 0], [-1, 0],
121
+ [0.5, 0.8660254], [-0.5, 0.8660254],
122
+ [0.5, -0.8660254], [-0.5, -0.8660254],
123
+ ];
124
+ const probe = (cx, cy) => `
125
+ {
126
+ vec2 c = ${p}c0 + vec2(${cx.toFixed(7)}, ${cy.toFixed(7)});
127
+ float f = 1.0 - smoothstep(0.0, ${p}radius,
128
+ length(c * ${p}size - ${p}dpos));
129
+ f *= ${p}damt;
130
+ float s = 1.0 + ${p}lift * f;
131
+ vec2 q = hp - c;
132
+ float hd = max(dot(abs(q), ${p}AX), abs(q).x);
133
+ // Covered by this cell's grown hexagon, and nearer than
134
+ // whatever we have so far.
135
+ if (hd <= 0.5 * s && s > ${p}bestS) {
136
+ ${p}bestS = s; ${p}bestC = c; ${p}bestF = f;
137
+ }
138
+ }`;
139
+ return `
140
+ {
141
+ vec2 hp = warped / ${p}size;
142
+ vec2 hr = vec2(1.0, 1.7320508), hh = hr * 0.5;
143
+ vec2 ha = mod(hp, hr) - hh, hb = mod(hp - hh, hr) - hh;
144
+ vec2 gv = dot(ha, ha) < dot(hb, hb) ? ha : hb;
145
+ vec2 ${p}AX = normalize(vec2(1.0, 1.7320508));
146
+ vec2 ${p}c0 = hp - gv;
147
+ // Seed with the owning cell. Its own hexagon always covers the
148
+ // fragment at any scale >= 1, so there is always a winner.
149
+ vec2 ${p}bestC = ${p}c0;
150
+ float ${p}bestF = (1.0 - smoothstep(0.0, ${p}radius,
151
+ length(${p}c0 * ${p}size - ${p}dpos))) * ${p}damt;
152
+ float ${p}bestS = 1.0 + ${p}lift * ${p}bestF;
153
+ ${NB.map(([x, y]) => probe(x, y)).join("")}
154
+ center = ${p}bestC * ${p}size;
155
+ // Divide by the winner's scale: the border test then reaches
156
+ // 0.5 further out (a bigger hexagon) and the sample moves in
157
+ // toward the centre (its content magnified to match), both by
158
+ // the same factor, so proportions are preserved exactly.
159
+ gv = (hp - ${p}bestC) / max(${p}bestS, 1e-3);
160
+ warped = center + gv * ${p}size;
161
+ gv = abs(gv);
162
+ // Border strength follows the SAME falloff as the scale, so a
163
+ // cell that has not been raised draws no border at all. Away
164
+ // from the pointer bestF is 0, which means scale 1, sampling
165
+ // untouched and edge 0 — bit-identical to the source image, so
166
+ // nothing reveals that an effect is attached until the pointer
167
+ // arrives. Pair with by:"hover" for a fully flush resting
168
+ // state; by:"mouse" holds amt at 1 and so keeps a permanent
169
+ // hotspot wherever the pointer last was.
170
+ edge = max(edge, smoothstep(0.44, 0.5,
171
+ max(dot(gv, ${p}AX), gv.x)) * ${p}bestF);
172
+ }`;
173
+ },
174
+ uniforms: (node, dpr) => ({
175
+ size: ["1f", (node.size || 24) * dpr],
176
+ // How much bigger a cell gets at the pointer, as a fraction:
177
+ // 0.3 means the nearest hexagons render at 1.3x. NOT scaled by
178
+ // dpr — it is a ratio, not a length. 0 disables the whole
179
+ // branch, so callers that never ask for it compile to exactly
180
+ // the shader they compiled to before.
181
+ lift: ["1f", node.lift != null ? node.lift : 0],
182
+ radius: ["1f", (node.radius || 200) * dpr],
183
+ }),
95
184
  },
96
185
 
97
186
  offset: {
@@ -234,6 +323,74 @@ const REGISTRY = {
234
323
  }),
235
324
  },
236
325
 
326
+ // Ordered dither: quantise the image to a few levels per channel and
327
+ // break the resulting banding with a Bayer threshold matrix, the way
328
+ // an indexed-colour display fakes shades it cannot address.
329
+ //
330
+ // { op: "dither", levels: 6 } // gentle, keeps colour
331
+ // { op: "dither", levels: 3, amount: 0.7 } // stronger posterise
332
+ // { op: "dither", mono: true, ink: "#0B1B2B" } // 1-bit, ink on paper
333
+ //
334
+ // Unlike `halftone`, which replaces the picture with ink coverage on
335
+ // paper, this keeps the original hues and only coarsens them — so it
336
+ // reads as texture over a photograph rather than as a print process.
337
+ //
338
+ // Stateless, so it renders on the snapshot backend. That matters:
339
+ // `stir` needs the HTML-in-Canvas live backend and silently does
340
+ // nothing without the origin trial, whereas this runs everywhere.
341
+ //
342
+ // `by` coarsens the pattern toward the driver focus, as halftone does.
343
+ dither: {
344
+ stage: "color",
345
+ decl: (p) => `
346
+ uniform float ${p}levels;
347
+ uniform float ${p}size;
348
+ uniform float ${p}amount;
349
+ uniform vec3 ${p}ink;
350
+ uniform vec3 ${p}paper;
351
+ uniform vec2 ${p}dpos;
352
+ uniform float ${p}damt;
353
+ uniform float ${p}radius;
354
+ // Bayer matrices by recursive bit-interleave rather than a
355
+ // 64-entry table: WebGL1 has no constant array indexing, and
356
+ // the nesting is exactly the recursive definition of the
357
+ // ordered-dither matrix.
358
+ float ${p}b2(vec2 a) {
359
+ a = floor(a);
360
+ return fract(a.x * 0.5 + a.y * a.y * 0.75);
361
+ }
362
+ float ${p}b4(vec2 a) { return ${p}b2(0.5 * a) * 0.25 + ${p}b2(a); }
363
+ float ${p}b8(vec2 a) { return ${p}b4(0.5 * a) * 0.25 + ${p}b2(a); }`,
364
+ code: (p, node) => `
365
+ {
366
+ float sz = max(${p}size, 1e-3);${node.by ? `
367
+ float fd = 1.0 - smoothstep(0.0, ${p}radius, length(frag - ${p}dpos));
368
+ sz *= 1.0 + fd * ${p}damt * 1.8;` : ``}
369
+ // Centre the threshold on zero so dithering does not lift or
370
+ // crush the overall exposure, only redistributes it.
371
+ float t = ${p}b8(frag / sz) - 0.5;
372
+ float lv = max(${p}levels, 1.0);
373
+ ${node.mono ? `
374
+ float lum = dot(col, vec3(0.299, 0.587, 0.114));
375
+ float q = step(0.5, lum + t);
376
+ vec3 dq = mix(${p}ink, ${p}paper, q);` : `
377
+ // Per channel: scale to level index, offset by the threshold,
378
+ // round, scale back. The +t before rounding is what turns a
379
+ // hard band edge into an interleaved pattern of the two
380
+ // neighbouring levels.
381
+ vec3 dq = floor(col * lv + 0.5 + t) / lv;`}
382
+ col = mix(col, clamp(dq, 0.0, 1.0), clamp(${p}amount, 0.0, 1.0));
383
+ }`,
384
+ uniforms: (node, dpr) => ({
385
+ levels: ["1f", node.levels != null ? node.levels : 6],
386
+ size: ["1f", (node.size != null ? node.size : 1) * dpr],
387
+ amount: ["1f", node.amount != null ? node.amount : 1],
388
+ ink: ["3fv", hexToRgb(node.ink || "#0B1B2B")],
389
+ paper: ["3fv", hexToRgb(node.paper || "#FFFFFF")],
390
+ radius: ["1f", (node.radius || 220) * dpr],
391
+ }),
392
+ },
393
+
237
394
  // Chromatic aberration: the only op that uses the displace stage. It
238
395
  // does not move the sample position itself, it sets `chroma`, the
239
396
  // per-channel split the sampler applies - red and blue are fetched
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
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.196
2
+ * nodality v1.0.198
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.196
2
+ * nodality v1.0.198
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.196
2
+ * nodality v1.0.198
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.196
2
+ * nodality v1.0.198
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.196",
3
+ "version": "1.0.198",
4
4
  "description": "A lightweight library for declarative UI elements.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",