nodality 1.0.224 → 1.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.
Files changed (231) hide show
  1. package/dist/animator.cjs.js +1 -1
  2. package/dist/animator.cjs.js.LICENSE.txt +1 -1
  3. package/dist/animator.esm.js.LICENSE.txt +1 -1
  4. package/dist/audionew.cjs.js +1 -1
  5. package/dist/audionew.cjs.js.LICENSE.txt +1 -1
  6. package/dist/audionew.esm.js.LICENSE.txt +1 -1
  7. package/dist/base.cjs.js +1 -1
  8. package/dist/base.cjs.js.LICENSE.txt +1 -1
  9. package/dist/base.esm.js.LICENSE.txt +1 -1
  10. package/dist/beta-desktop-bar.cjs.js +1 -1
  11. package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
  12. package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
  13. package/dist/beta-mobile-bar.cjs.js +1 -1
  14. package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
  15. package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
  16. package/dist/bundle.umd.js +1 -1
  17. package/dist/bundle.umd.js.LICENSE.txt +1 -1
  18. package/dist/button.cjs.js +1 -1
  19. package/dist/button.cjs.js.LICENSE.txt +1 -1
  20. package/dist/button.esm.js.LICENSE.txt +1 -1
  21. package/dist/card-getter.cjs.js.LICENSE.txt +1 -1
  22. package/dist/card-getter.esm.js.LICENSE.txt +1 -1
  23. package/dist/center.cjs.js +1 -1
  24. package/dist/center.cjs.js.LICENSE.txt +1 -1
  25. package/dist/center.esm.js.LICENSE.txt +1 -1
  26. package/dist/checkbox.cjs.js +1 -1
  27. package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
  28. package/dist/checkbox.esm.js.LICENSE.txt +1 -1
  29. package/dist/code.cjs.js +1 -1
  30. package/dist/code.cjs.js.LICENSE.txt +1 -1
  31. package/dist/code.esm.js.LICENSE.txt +1 -1
  32. package/dist/container.cjs.js +1 -1
  33. package/dist/container.cjs.js.LICENSE.txt +1 -1
  34. package/dist/container.esm.js.LICENSE.txt +1 -1
  35. package/dist/data-list.cjs.js.LICENSE.txt +1 -1
  36. package/dist/data-list.esm.js.LICENSE.txt +1 -1
  37. package/dist/designer.cjs.js +1 -1
  38. package/dist/designer.cjs.js.LICENSE.txt +1 -1
  39. package/dist/designer.esm.js +1 -1
  40. package/dist/designer.esm.js.LICENSE.txt +1 -1
  41. package/dist/element-mapper.cjs.js +1 -1
  42. package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
  43. package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
  44. package/dist/finalresult.esm.js +1 -1
  45. package/dist/finalresult.esm.js.LICENSE.txt +1 -1
  46. package/dist/flex-card.cjs.js +1 -1
  47. package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
  48. package/dist/flex-card.esm.js.LICENSE.txt +1 -1
  49. package/dist/flex-grid.cjs.js +1 -1
  50. package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
  51. package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
  52. package/dist/flex-row.cjs.js +1 -1
  53. package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
  54. package/dist/flex-row.esm.js.LICENSE.txt +1 -1
  55. package/dist/floating-input.cjs.js +1 -1
  56. package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
  57. package/dist/floating-input.esm.js.LICENSE.txt +1 -1
  58. package/dist/free.cjs.js +1 -1
  59. package/dist/free.cjs.js.LICENSE.txt +1 -1
  60. package/dist/free.esm.js.LICENSE.txt +1 -1
  61. package/dist/horizontal-scroller.cjs.js.LICENSE.txt +1 -1
  62. package/dist/horizontal-scroller.esm.js.LICENSE.txt +1 -1
  63. package/dist/image-picker.cjs.js +1 -1
  64. package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
  65. package/dist/image-picker.esm.js.LICENSE.txt +1 -1
  66. package/dist/image.cjs.js +1 -1
  67. package/dist/image.cjs.js.LICENSE.txt +1 -1
  68. package/dist/image.esm.js.LICENSE.txt +1 -1
  69. package/dist/index.cjs.js +1 -1
  70. package/dist/index.cjs.js.LICENSE.txt +1 -1
  71. package/dist/index.d.ts +1 -1
  72. package/dist/index.esm.js +1 -1
  73. package/dist/index.esm.js.LICENSE.txt +1 -1
  74. package/dist/keyframe-animation.cjs.js.LICENSE.txt +1 -1
  75. package/dist/keyframe-animation.esm.js.LICENSE.txt +1 -1
  76. package/dist/link-getter.cjs.js +1 -1
  77. package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
  78. package/dist/link-getter.esm.js.LICENSE.txt +1 -1
  79. package/dist/link.cjs.js +1 -1
  80. package/dist/link.cjs.js.LICENSE.txt +1 -1
  81. package/dist/link.esm.js.LICENSE.txt +1 -1
  82. package/dist/meta-adder.cjs.js +1 -1
  83. package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
  84. package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
  85. package/dist/modal-2025.cjs.js +1 -1
  86. package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
  87. package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
  88. package/dist/multiswitcher.cjs.js +1 -1
  89. package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
  90. package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
  91. package/dist/new-nav-bar.cjs.js +1 -1
  92. package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
  93. package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
  94. package/dist/picker.cjs.js +1 -1
  95. package/dist/picker.cjs.js.LICENSE.txt +1 -1
  96. package/dist/picker.esm.js.LICENSE.txt +1 -1
  97. package/dist/progress.cjs.js +1 -1
  98. package/dist/progress.cjs.js.LICENSE.txt +1 -1
  99. package/dist/progress.esm.js.LICENSE.txt +1 -1
  100. package/dist/radio.cjs.js.LICENSE.txt +1 -1
  101. package/dist/radio.esm.js.LICENSE.txt +1 -1
  102. package/dist/range.cjs.js.LICENSE.txt +1 -1
  103. package/dist/range.esm.js.LICENSE.txt +1 -1
  104. package/dist/scroll-video.cjs.js.LICENSE.txt +1 -1
  105. package/dist/scroll-video.esm.js.LICENSE.txt +1 -1
  106. package/dist/side-bar.cjs.js +1 -1
  107. package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
  108. package/dist/side-bar.esm.js.LICENSE.txt +1 -1
  109. package/dist/side-nav-bar.cjs.js +1 -1
  110. package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
  111. package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
  112. package/dist/simple-bar.cjs.js +1 -1
  113. package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
  114. package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
  115. package/dist/slider-2025.cjs.js +1 -1
  116. package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
  117. package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
  118. package/dist/spacer.cjs.js +1 -1
  119. package/dist/spacer.cjs.js.LICENSE.txt +1 -1
  120. package/dist/spacer.esm.js.LICENSE.txt +1 -1
  121. package/dist/stack.cjs.js +1 -1
  122. package/dist/stack.cjs.js.LICENSE.txt +1 -1
  123. package/dist/stack.esm.js.LICENSE.txt +1 -1
  124. package/dist/stacker.cjs.js.LICENSE.txt +1 -1
  125. package/dist/stacker.esm.js.LICENSE.txt +1 -1
  126. package/dist/table.cjs.js +1 -1
  127. package/dist/table.cjs.js.LICENSE.txt +1 -1
  128. package/dist/table.esm.js.LICENSE.txt +1 -1
  129. package/dist/text-field.cjs.js +1 -1
  130. package/dist/text-field.cjs.js.LICENSE.txt +1 -1
  131. package/dist/text-field.esm.js.LICENSE.txt +1 -1
  132. package/dist/text.cjs.js +1 -1
  133. package/dist/text.cjs.js.LICENSE.txt +1 -1
  134. package/dist/text.esm.js.LICENSE.txt +1 -1
  135. package/dist/theme.cjs.js.LICENSE.txt +1 -1
  136. package/dist/theme.esm.js.LICENSE.txt +1 -1
  137. package/dist/transform-anim.cjs.js.LICENSE.txt +1 -1
  138. package/dist/transform-anim.esm.js.LICENSE.txt +1 -1
  139. package/dist/ulist.cjs.js +1 -1
  140. package/dist/ulist.cjs.js.LICENSE.txt +1 -1
  141. package/dist/ulist.esm.js.LICENSE.txt +1 -1
  142. package/dist/video.cjs.js +1 -1
  143. package/dist/video.cjs.js.LICENSE.txt +1 -1
  144. package/dist/video.esm.js.LICENSE.txt +1 -1
  145. package/dist/wrap.cjs.js +1 -1
  146. package/dist/wrap.cjs.js.LICENSE.txt +1 -1
  147. package/dist/wrap.esm.js.LICENSE.txt +1 -1
  148. package/dist/zoom-card.cjs.js +1 -1
  149. package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
  150. package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
  151. package/layout/animator.js +1 -1
  152. package/layout/audio.js +1 -1
  153. package/layout/audionew.js +1 -1
  154. package/layout/base.js +1 -1
  155. package/layout/beta-desktop-bar.js +1 -1
  156. package/layout/beta-mobile-bar.js +1 -1
  157. package/layout/button.js +1 -1
  158. package/layout/center.js +1 -1
  159. package/layout/checkbox.js +1 -1
  160. package/layout/circle.js +1 -1
  161. package/layout/code.js +1 -1
  162. package/layout/container.js +1 -1
  163. package/layout/dropdown-2025.js +1 -1
  164. package/layout/flex-card.js +1 -1
  165. package/layout/flex-grid.js +1 -1
  166. package/layout/flex-row.js +1 -1
  167. package/layout/form-components/custom.js +1 -1
  168. package/layout/form-components/data-list.js +1 -1
  169. package/layout/form-components/floating-input.js +1 -1
  170. package/layout/form-components/form-all.js +1 -1
  171. package/layout/form-components/form.js +1 -1
  172. package/layout/form-components/image-picker.js +1 -1
  173. package/layout/form-components/picker.js +1 -1
  174. package/layout/form-components/radio.js +1 -1
  175. package/layout/form-components/radiogroup.js +1 -1
  176. package/layout/form-components/range.js +1 -1
  177. package/layout/free.js +1 -1
  178. package/layout/grid-switcher.js +1 -1
  179. package/layout/grid.js +1 -1
  180. package/layout/horizontal-scroller.js +1 -1
  181. package/layout/image.js +1 -1
  182. package/layout/index.js +1 -1
  183. package/layout/link.js +1 -1
  184. package/layout/list.js +1 -1
  185. package/layout/meta-adder.js +1 -1
  186. package/layout/modal-2025.js +1 -1
  187. package/layout/morph.js +1 -1
  188. package/layout/multiswitcher.js +1 -1
  189. package/layout/nav-bar.js +1 -1
  190. package/layout/nav-factor/custom-div.js +1 -1
  191. package/layout/new-nav-bar.js +1 -1
  192. package/layout/polygon.js +1 -1
  193. package/layout/prerender-site.js +1 -1
  194. package/layout/prerender.js +1 -1
  195. package/layout/progress.js +1 -1
  196. package/layout/row.js +1 -1
  197. package/layout/scroll-video.js +1 -1
  198. package/layout/side-bar.js +1 -1
  199. package/layout/side-nav-bar.js +1 -1
  200. package/layout/simple-bar.js +1 -1
  201. package/layout/slider-2025.js +1 -1
  202. package/layout/spacer.js +1 -1
  203. package/layout/stack.js +1 -1
  204. package/layout/svg.js +1 -1
  205. package/layout/switcher.js +1 -1
  206. package/layout/table.js +1 -1
  207. package/layout/text-field.js +1 -1
  208. package/layout/text.js +1 -1
  209. package/layout/ulist.js +1 -1
  210. package/layout/video.js +1 -1
  211. package/layout/wrap.js +1 -1
  212. package/layout/zoom-card.js +1 -1
  213. package/lib/card-getter.js +1 -1
  214. package/lib/codegen.js +1 -1
  215. package/lib/data.js +1 -1
  216. package/lib/designer.js +1 -1
  217. package/lib/element-mapper.js +1 -1
  218. package/lib/keyframe-animation.js +1 -1
  219. package/lib/link-getter.js +1 -1
  220. package/lib/morph-node.js +1 -1
  221. package/lib/raster-inspect.js +1 -1
  222. package/lib/raster-ops.js +80 -3
  223. package/lib/raster-presets.js +16 -1
  224. package/lib/scroll-video.js +1 -1
  225. package/lib/seo.js +1 -1
  226. package/lib/stacker.js +1 -1
  227. package/lib/suggest.js +1 -1
  228. package/lib/theme.js +1 -1
  229. package/lib/transform-anim.js +1 -1
  230. package/lib/transition.js +1 -1
  231. package/package.json +1 -1
package/lib/raster-ops.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.224
2
+ * nodality v1.1.0
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -2031,6 +2031,14 @@ const FRAMEWORK_DOC = {
2031
2031
  default: null, unit: "name",
2032
2032
  summary: "element ids this node applies to, e.g. [\"#hero\"]",
2033
2033
  },
2034
+ side: {
2035
+ default: null, unit: "name", structural: true,
2036
+ summary: "\"old\" or \"new\" — scope this op to ONE half of a morph " +
2037
+ "instead of the blended result, so the outgoing and incoming " +
2038
+ "states can be art-directed differently. Colour-stage ops only: " +
2039
+ "both sides share one sampling coordinate, so a sided warp has " +
2040
+ "no meaning. Ignored outside a transition.",
2041
+ },
2034
2042
  by: {
2035
2043
  default: "static", unit: "name", structural: true,
2036
2044
  summary: `what steers the effect: ${DRIVER_NAMES.join(", ")}. ` +
@@ -2222,8 +2230,71 @@ function buildFragmentShader(recs, flat, probe, transition) {
2222
2230
  if (def) decls += def.decl(`u${i}_`, node) + "\n";
2223
2231
  });
2224
2232
 
2233
+ // PER-SIDE effects. A node may carry `side: "old" | "new"`, which
2234
+ // scopes it to one half of a morph instead of the blended result.
2235
+ //
2236
+ // Everything else in a transition chain decorates the CROSSFADE — it
2237
+ // runs after old and new have already been mixed, so both ends get
2238
+ // the same treatment. That cannot express "the outgoing state burns
2239
+ // out while the incoming one develops", which is the thing a designer
2240
+ // actually reaches for. A sided op runs on its own side's colour
2241
+ // BEFORE nodBlend sees it.
2242
+ //
2243
+ // Colour stage only, and deliberately: warp/displace ops rewrite the
2244
+ // sampling coordinate, and there is one coordinate shared by both
2245
+ // sides — honouring `side` there would mean two independent
2246
+ // coordinate pipelines. A sided warp is rejected loudly rather than
2247
+ // silently ignored.
2248
+ const sideOf = (rec) => {
2249
+ const v = rec && rec.node && rec.node.side;
2250
+ if (v !== "old" && v !== "new") return null;
2251
+ const def = REGISTRY[rec.node.op];
2252
+ const stages = def ? (Array.isArray(def.stage) ? def.stage : [def.stage]) : [];
2253
+ if (!stages.every((st) => st === "color")) {
2254
+ console.warn(`[nodality] "${rec.node.op}" is a ${stages.join("+")} op, ` +
2255
+ `so side:"${v}" cannot apply to it — a sided op must be colour-only, ` +
2256
+ `because both sides share one sampling coordinate. Running it on ` +
2257
+ `the blended result instead.`);
2258
+ return null;
2259
+ }
2260
+ if (!transition) {
2261
+ console.warn(`[nodality] side:"${v}" has no meaning without a ` +
2262
+ `transition — there is only one image. Ignoring it.`);
2263
+ return null;
2264
+ }
2265
+ return v;
2266
+ };
2267
+ const mainRecs = recs.filter((r) => !sideOf(r));
2268
+ const oldRecs = recs.filter((r) => sideOf(r) === "old");
2269
+ const newRecs = recs.filter((r) => sideOf(r) === "new");
2270
+
2225
2271
  const buckets = emptyBuckets();
2226
- emitStages(recs, buckets);
2272
+ emitStages(mainRecs, buckets);
2273
+
2274
+ // One scope per side, with the colour stage variables declared local
2275
+ // so an op that touches edgeCol/ovA compiles here exactly as it does
2276
+ // in main(). `frag` is the sample position, which is what a sided op
2277
+ // means by "where am I".
2278
+ const sideBlock = (list, src) => {
2279
+ if (!list.length) return "";
2280
+ const b = emptyBuckets();
2281
+ emitStages(list, b);
2282
+ if (!b.color) return "";
2283
+ const decls = STAGE_VARS.color
2284
+ .filter((v) => v !== "col")
2285
+ .map((v) => ` ${glslType(v)} ${v} = ${glslType(v) === "vec3"
2286
+ ? "vec3(0.0)" : "0.0"};`).join("\n");
2287
+ return ` {
2288
+ vec2 frag = p;
2289
+ vec3 col = ${src}.rgb;
2290
+ ${decls}
2291
+ ${b.color}
2292
+ ${src}.rgb = col;
2293
+ }
2294
+ `;
2295
+ };
2296
+ const oldSideCode = sideBlock(oldRecs, "o");
2297
+ const newSideCode = sideBlock(newRecs, "n");
2227
2298
  const { field, warp, cell, displace, color } = buckets;
2228
2299
  const nodes = flat;
2229
2300
  // Compositing, in three layers (all straight-alpha):
@@ -2281,6 +2352,12 @@ uniform vec2 u_res;
2281
2352
  uniform vec2 u_mouse;
2282
2353
  uniform float u_time;
2283
2354
  uniform float u_t; // phase T1: transition progress, 0..1
2355
+
2356
+ // Op uniforms are declared HERE, above the transition helpers, because a
2357
+ // per-side op's code is emitted inside nodSampleAt. GLSL requires
2358
+ // declaration before use, and with the declarations further down every
2359
+ // sided op failed to compile with "'u0_amount' : undeclared identifier".
2360
+ ${probeDecl}${decls}
2284
2361
  ${transition ? `
2285
2362
  // ── phase T2: transition mode ──────────────────────────────────────
2286
2363
  // Two captures instead of one. u_tex is the NEW element, u_old the
@@ -2373,6 +2450,7 @@ vec4 nodSampleAt(vec2 p) {
2373
2450
  clamp(un, 0.001, 0.999));
2374
2451
  o.a *= nodInBox(uo);
2375
2452
  n.a *= nodInBox(un);
2453
+ ${oldSideCode}${newSideCode}
2376
2454
  // The threshold each pixel flips at. Mostly a COHERENT ramp down the
2377
2455
  // box with a little grain on top — pure white noise chooses correctly
2378
2456
  // (never two legible images at once) but reads as television static
@@ -2383,7 +2461,6 @@ vec4 nodSampleAt(vec2 p) {
2383
2461
  float d = ramp * 0.82 + grain * 0.18;
2384
2462
  return nodBlend(o, n, u_t, d);
2385
2463
  }` : ""}
2386
- ${probeDecl}${decls}
2387
2464
  void main() {
2388
2465
  vec2 fc = ${fragCoord};
2389
2466
  vec2 frag = vec2(fc.x, u_res.y - fc.y);
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.224
2
+ * nodality v1.1.0
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -70,6 +70,21 @@ const PRESETS = {
70
70
  ease: "in-out" },
71
71
  ],
72
72
  },
73
+ // The first preset that treats the two halves of a morph as separate
74
+ // things: the outgoing state burns to ink while the incoming one
75
+ // resolves out of a screen. A crossfade decorated after the blend
76
+ // cannot express this — both ends would get the same treatment.
77
+ "t-split": {
78
+ summary: "Per-side morph: the old state posterises to duotone while " +
79
+ "the new one resolves through a halftone screen.",
80
+ nodes: [
81
+ { op: "duotone", side: "old", amount: [0, 1, 1],
82
+ dark: "#0B1B2B", light: "#1abc9c" },
83
+ { op: "halftone", side: "new", size: [10, 6, 2], amount: [1, 1, 0],
84
+ softness: 0.35, angle: 15 },
85
+ ],
86
+ },
87
+
73
88
  "t-bloom": {
74
89
  summary: "A soft halftone bloom through the middle of the morph.",
75
90
  nodes: [
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.224
2
+ * nodality v1.1.0
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.224
2
+ * nodality v1.1.0
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.224
2
+ * nodality v1.1.0
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/suggest.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.224
2
+ * nodality v1.1.0
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.224
2
+ * nodality v1.1.0
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.224
2
+ * nodality v1.1.0
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/transition.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.224
2
+ * nodality v1.1.0
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.224",
3
+ "version": "1.1.0",
4
4
  "description": "A lightweight library for declarative UI elements.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",