@madojs/mado 0.8.0 → 0.9.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.
@@ -77,6 +77,13 @@ export function router(routes, options = {}) {
77
77
  const me = e;
78
78
  if (me.metaKey || me.ctrlKey || me.shiftKey || me.altKey)
79
79
  return;
80
+ // Respect intentional non-SPA links: opening in a new tab/window or a
81
+ // download must keep native behaviour. (FABLE_REPORT.md finding #9)
82
+ const target = a.getAttribute("target");
83
+ if (target && target !== "_self")
84
+ return;
85
+ if (a.hasAttribute("download"))
86
+ return;
80
87
  const url = new URL(a.href, location.href);
81
88
  if (url.origin !== location.origin)
82
89
  return;
@@ -142,7 +149,12 @@ export function router(routes, options = {}) {
142
149
  history.pushState(null, "", to);
143
150
  currentScrollKey = locationKey();
144
151
  path.set(location.pathname);
145
- if (useScrollRestoration)
152
+ // An in-page #hash must scroll to its target even when the pathname is
153
+ // unchanged (signal dedup would otherwise swallow the navigation and
154
+ // leave anchor links dead). (FABLE_REPORT.md finding #9)
155
+ if (location.hash)
156
+ scrollToHash(location.hash);
157
+ else if (useScrollRestoration)
146
158
  scrollToTop();
147
159
  if (useFocusManagement)
148
160
  scheduleFocusReset();
@@ -223,7 +235,10 @@ export function navigate(to, opts) {
223
235
  // popstate is NOT dispatched automatically on pushState/replaceState,
224
236
  // so we dispatch it manually — all active routers will hear and update.
225
237
  window.dispatchEvent(new PopStateEvent("popstate"));
226
- scrollToTop();
238
+ if (location.hash)
239
+ scrollToHash(location.hash);
240
+ else
241
+ scrollToTop();
227
242
  scheduleFocusReset();
228
243
  }
229
244
  function locationKey() {
@@ -243,6 +258,45 @@ function restoreScroll(positions, key) {
243
258
  function scrollToTop() {
244
259
  scrollTo({ top: 0, left: 0 });
245
260
  }
261
+ function scrollToHash(hash) {
262
+ const scroll = () => {
263
+ const target = hashTarget(hash);
264
+ if (!target)
265
+ return false;
266
+ try {
267
+ target.scrollIntoView({ block: "start", inline: "nearest" });
268
+ }
269
+ catch {
270
+ try {
271
+ target.scrollIntoView();
272
+ }
273
+ catch {
274
+ /* noop */
275
+ }
276
+ }
277
+ return true;
278
+ };
279
+ if (scroll())
280
+ return;
281
+ // New-route hash targets are often rendered by the reactive route effect
282
+ // after `path.set()`, so try once more on the next microtask.
283
+ queueMicrotask(() => {
284
+ scroll();
285
+ });
286
+ }
287
+ function hashTarget(hash) {
288
+ const raw = hash.startsWith("#") ? hash.slice(1) : hash;
289
+ if (!raw)
290
+ return null;
291
+ let id = raw;
292
+ try {
293
+ id = decodeURIComponent(raw);
294
+ }
295
+ catch {
296
+ /* keep raw hash text */
297
+ }
298
+ return document.getElementById(id);
299
+ }
246
300
  function scrollTo(options) {
247
301
  const maybeWindow = window;
248
302
  if (typeof maybeWindow.scrollTo !== "function")
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../../src/router/navigation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../../src/router/navigation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAe,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EACL,OAAO,EACP,UAAU,GAIX,MAAM,YAAY,CAAC;AAyCpB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,MAAM,CACpB,MAAc,EACd,UAAyB,EAAE;IAE3B,MAAM,kBAAkB,GAAG,OAAO,CAAC,eAAe,KAAK,KAAK,CAAC;IAC7D,MAAM,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,KAAK,KAAK,CAAC;IACjE,MAAM,kBAAkB,GAAG,OAAO,CAAC,eAAe,KAAK,KAAK,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,QAAQ,GACZ,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,IAAI,eAAe,EAAE,CAAC;IAE/D,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAyC,CAAC;IACzE,IAAI,gBAAgB,GAAG,WAAW,EAAE,CAAC;IACrC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,IAAI,GAAG,OAA8D,CAAC;IAC5E,MAAM,yBAAyB,GAAG,IAAI,CAAC,iBAAiB,CAAC;IACzD,IAAI,oBAAoB,IAAI,mBAAmB,IAAI,IAAI,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC;YAClC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;gBACjB,IAAI,CAAC,iBAAiB,GAAG,yBAAyB,CAAC;YACrD,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,UAAU;QACZ,CAAC;IACH,CAAC;IAED,cAAc;IACd,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,QAAQ;YAAE,OAAO;QACrB,IAAI,oBAAoB;YAAE,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;QACxE,gBAAgB,GAAG,WAAW,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,oBAAoB;YAAE,aAAa,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;QAC3E,IAAI,kBAAkB;YAAE,kBAAkB,EAAE,CAAC;IAC/C,CAAC,CAAC;IACF,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC3C,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;IAEnE,gDAAgD;IAChD,MAAM,OAAO,GAAG,CAAC,CAAQ,EAAE,EAAE;QAC3B,IAAI,QAAQ;YAAE,OAAO;QACrB,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QACxC,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,IAAK,CAAgB,CAAC,gBAAgB;YAAE,OAAO;QAC/C,IAAK,CAAgB,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC3C,MAAM,EAAE,GAAG,CAAe,CAAC;QAC3B,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,MAAM;YAAE,OAAO;QACjE,sEAAsE;QACtE,oEAAoE;QACpE,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,MAAM,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO;QACzC,IAAI,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC;YAAE,OAAO;QACvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;YAAE,OAAO;QAC3C,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC;IACF,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpE,sEAAsE;IACtE,IAAI,aAAa,GAAyC,IAAI,CAAC;IAC/D,MAAM,WAAW,GAAG,CAAC,CAAQ,EAAE,EAAE;QAC/B,IAAI,QAAQ;YAAE,OAAO;QACrB,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,OAAO;QAC9B,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,sCAAsC,CAAC,CAAC;QAChE,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,IAAI,aAAa;YAAE,YAAY,CAAC,aAAa,CAAC,CAAC;QAC/C,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;oBAAE,OAAO;gBAC3C,OAAO,CAAC,QAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU;YACZ,CAAC;QACH,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,aAAa,CAAC,CAAC;YAC5B,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IACF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACpD,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAClD,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACvD,QAAQ,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACrD,IAAI,aAAa;YAAE,YAAY,CAAC,aAAa,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAc;QACrB,IAAI,EAAE,GAAG,EAAE;YACT,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACjB,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YAClC,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACxC,OAAO,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI;QACJ,QAAQ,CAAC,EAAE,EAAE,IAAI;YACf,MAAM,KAAK,GAAG,GAAG,EAAE;gBACjB,IAAI,oBAAoB;oBAAE,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;gBACxE,IAAI,IAAI,EAAE,OAAO;oBAAE,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;;oBACjD,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBACrC,gBAAgB,GAAG,WAAW,EAAE,CAAC;gBACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAC5B,uEAAuE;gBACvE,qEAAqE;gBACrE,yDAAyD;gBACzD,IAAI,QAAQ,CAAC,IAAI;oBAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;qBAC1C,IAAI,oBAAoB;oBAAE,WAAW,EAAE,CAAC;gBAC7C,IAAI,kBAAkB;oBAAE,kBAAkB,EAAE,CAAC;YAC/C,CAAC,CAAC;YAEF,wDAAwD;YACxD,+DAA+D;YAC/D,4CAA4C;YAC5C,MAAM,GAAG,GAAG,QAEX,CAAC;YACF,IAAI,kBAAkB,IAAI,OAAO,GAAG,CAAC,mBAAmB,KAAK,UAAU,EAAE,CAAC;gBACxE,GAAG,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QACD,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,CAAC,EAAE,CAAC;gBACN,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU;gBACZ,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,CAAQ,EAAE,QAAgB;IAC5C,MAAM,WAAW,GAAG,CAAC,IAAa,EAA4B,EAAE;QAC9D,IAAI,CAAC,CAAC,IAAI,YAAY,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC9C,OAAO,KAA0B,CAAC;IACpC,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iDAAiD;AACjD,SAAS,eAAe;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAA,aAAa,QAAQ,CAAC,QAAQ,QAAQ,CAAC,CAAC;AACxE,CAAC;AAED,mCAAmC;AAEnC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAU,EAAE,IAA4B;IAC/D,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO;IAC5E,IAAI,IAAI,EAAE,OAAO;QAAE,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;;QACjD,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACrC,sEAAsE;IACtE,wEAAwE;IACxE,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;IACpD,IAAI,QAAQ,CAAC,IAAI;QAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;;QAC1C,WAAW,EAAE,CAAC;IACnB,kBAAkB,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,GAAG,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,UAAU,CACjB,SAAqD,EACrD,GAAW;IAEX,MAAM,WAAW,GAAG,MAKnB,CAAC;IACF,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE;QACjB,IAAI,EAAE,WAAW,CAAC,OAAO,IAAI,WAAW,CAAC,WAAW,IAAI,CAAC;QACzD,GAAG,EAAE,WAAW,CAAC,OAAO,IAAI,WAAW,CAAC,WAAW,IAAI,CAAC;KACzD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CACpB,SAAqD,EACrD,GAAW;IAEX,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACtD,QAAQ,CAAC,GAAG,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,WAAW;IAClB,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU;YACZ,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,IAAI,MAAM,EAAE;QAAE,OAAO;IACrB,yEAAyE;IACzE,8DAA8D;IAC9D,cAAc,CAAC,GAAG,EAAE;QAClB,MAAM,EAAE,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,EAAE,GAAG,GAAG,CAAC;IACb,IAAI,CAAC;QACH,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,QAAQ,CAAC,OAAwB;IACxC,MAAM,WAAW,GAAG,MAEnB,CAAC;IACF,IAAI,OAAO,WAAW,CAAC,QAAQ,KAAK,UAAU;QAAE,OAAO;IACvD,IAAI,CAAC;QACH,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,UAAU;IACZ,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB;IACzB,cAAc,CAAC,GAAG,EAAE;QAClB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CACnC,4CAA4C,CAC7C,CAAC;QACF,IAAI,CAAC,CAAC,MAAM,YAAY,WAAW,CAAC;YAAE,OAAO;QAC7C,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YAAE,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC5E,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU;YACZ,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mCAAmC;AACnC,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,oEAAoE;AACpE,mEAAmE;AAEnE,IAAI,QAAQ,GAA0B,IAAI,CAAC;AAE3C,SAAS,cAAc;IACrB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,QAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,IAAqB,EAAE,IAAa;IACrD,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,CAC3E,KAAK,EACL,EAAE,CACH,CAAC;IACF,IAAI,IAAI;QAAE,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;;QACtC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IACzC,cAAc,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC;AAOD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,YAAY,GAAG,EAAE;IACxD,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE;QACjB,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC;IAC1C,CAAC,CAAe,CAAC;IAEjB,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACzB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;YACnD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC7B,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,KAAK,CAAC,CAAC;IACzC,CAAC,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -67,8 +67,29 @@ function cleanupTracker(tracker) {
67
67
  }
68
68
  // ---------- Scheduler ----------
69
69
  const pending = new Set();
70
+ // Reconciles for observed `equals`-computeds whose deps changed inside a batch.
71
+ // Deferred to batch end so they recompute once, on fully-applied (consistent)
72
+ // state, instead of eagerly inside each set() on half-applied state.
73
+ // (FABLE_REPORT.md finding #4)
74
+ const deferredEquals = new Set();
70
75
  let batchDepth = 0;
71
76
  let flushScheduled = false;
77
+ /** Run all deferred equals-computed reconciles; cascades may enqueue more. */
78
+ function drainDeferredEquals() {
79
+ while (deferredEquals.size > 0) {
80
+ const items = [...deferredEquals];
81
+ deferredEquals.clear();
82
+ for (const fn of items) {
83
+ try {
84
+ fn();
85
+ }
86
+ catch (err) {
87
+ // eslint-disable-next-line no-console
88
+ console.error("[mado] deferred computed reconcile threw:", err);
89
+ }
90
+ }
91
+ }
92
+ }
72
93
  function schedule(sub) {
73
94
  pending.add(sub);
74
95
  if (batchDepth > 0)
@@ -80,6 +101,9 @@ function schedule(sub) {
80
101
  }
81
102
  function flush() {
82
103
  flushScheduled = false;
104
+ // Defensive: reconcile any deferred equals-computeds before running effects,
105
+ // so effects always observe settled computed values.
106
+ drainDeferredEquals();
83
107
  const runCounts = new Map();
84
108
  // guard against Set modification during iteration
85
109
  while (pending.size > 0) {
@@ -116,9 +140,14 @@ export function batch(fn) {
116
140
  }
117
141
  finally {
118
142
  batchDepth--;
119
- if (batchDepth === 0 && pending.size > 0 && !flushScheduled) {
120
- flushScheduled = true;
121
- queueMicrotask(flush);
143
+ if (batchDepth === 0) {
144
+ // Reconcile deferred equals-computeds now that all sets are applied and
145
+ // state is consistent. This may enqueue effects into `pending`.
146
+ drainDeferredEquals();
147
+ if (pending.size > 0 && !flushScheduled) {
148
+ flushScheduled = true;
149
+ queueMicrotask(flush);
150
+ }
122
151
  }
123
152
  }
124
153
  }
@@ -187,6 +216,21 @@ export function computed(fn, options = {}) {
187
216
  let dirty = true;
188
217
  let hasValue = false;
189
218
  let computing = false;
219
+ // Recompute an observed equals-computed and notify only if the value
220
+ // actually changed. Extracted so it can run eagerly (outside a batch) or
221
+ // deferred to batch end (inside a batch), where it sees consistent state.
222
+ const reconcileEquals = () => {
223
+ if (subscribers.size === 0) {
224
+ dirty = true;
225
+ suspend();
226
+ return;
227
+ }
228
+ const prevValue = value;
229
+ recompute();
230
+ if (hasValue && options.equals(prevValue, value))
231
+ return;
232
+ notifySubscribers();
233
+ };
190
234
  const onInvalidate = () => {
191
235
  // dep changed → mark dirty synchronously and cascade.
192
236
  // Sync subscribers (other computed) are triggered immediately — they also
@@ -199,11 +243,15 @@ export function computed(fn, options = {}) {
199
243
  return;
200
244
  }
201
245
  if (options.equals && hasValue) {
202
- const prevValue = value;
203
- recompute();
204
- if (options.equals(prevValue, value))
246
+ // Inside a batch, defer the recompute+compare to batch end so it runs
247
+ // once on fully-applied state instead of eagerly on half-applied state
248
+ // (which would observe a mixed snapshot and could notify spuriously or
249
+ // run O(number of sets) times). (FABLE_REPORT.md finding #4)
250
+ if (batchDepth > 0) {
251
+ deferredEquals.add(reconcileEquals);
205
252
  return;
206
- notifySubscribers();
253
+ }
254
+ reconcileEquals();
207
255
  return;
208
256
  }
209
257
  dirty = true;
@@ -1 +1 @@
1
- {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/signal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/signal.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,10 @@
2
2
 
3
3
  > One right way. Strict contracts. No magic.
4
4
 
5
- Mado is not just a framework it is a **set of conventions**. If you follow them,
6
- the project stays understandable even with 200 screens and 5 developers. If you
5
+ Mado is a framework for teams building admin panels, internal tools and
6
+ business SPA apps that should be easy to build and boring to maintain. To
7
+ achieve that, it enforces a **set of conventions**. If you follow them, the
8
+ project stays understandable even with 200 screens and 5 developers. If you
7
9
  break them — types and the linter will tell you immediately.
8
10
 
9
11
  ## Principles
@@ -40,13 +42,21 @@ all write the same way.
40
42
 
41
43
  ```ts
42
44
  // src/components/user-card.ts
43
- import { component, html, css } from '@madojs/mado';
44
-
45
- component('x-user-card', () => {
46
- return () => html`<div class="card"><slot/></div>`;
47
- }, {
48
- styles: css`.card { padding: 1rem; }`,
49
- });
45
+ import { component, html, css } from "@madojs/mado";
46
+
47
+ component(
48
+ "x-user-card",
49
+ () => {
50
+ return () => html`<div class="card"><slot /></div>`;
51
+ },
52
+ {
53
+ styles: css`
54
+ .card {
55
+ padding: 1rem;
56
+ }
57
+ `,
58
+ },
59
+ );
50
60
  ```
51
61
 
52
62
  `import './components/user-card.js'` **registers** the component via
@@ -61,7 +71,7 @@ component('x-user-card', () => {
61
71
  const user = resource(() => `/api/users/${id()}`, jsonFetcher());
62
72
 
63
73
  // writing → mutation
64
- const save = mutation(api.save, { invalidates: ['/api/users*'] });
74
+ const save = mutation(api.save, { invalidates: ["/api/users*"] });
65
75
  ```
66
76
 
67
77
  This provides caching, cancellation, error handling, and auto-invalidation.
@@ -70,11 +80,11 @@ This provides caching, cancellation, error handling, and auto-invalidation.
70
80
 
71
81
  ```ts
72
82
  // src/pages/user-profile.ts
73
- import { page, html, resource, jsonFetcher } from '@madojs/mado';
83
+ import { page, html, resource, jsonFetcher } from "@madojs/mado";
74
84
 
75
85
  export default page({
76
86
  title: ({ id }) => `User #${id}`,
77
- view: ({ params }) => html`...`,
87
+ view: ({ params }) => html`...`,
78
88
  });
79
89
  ```
80
90
 
@@ -99,6 +109,7 @@ See [`01-routing.md`](./01-routing.md).
99
109
  ## When in doubt
100
110
 
101
111
  If you are asking "what's the best way here?" — that is a signal that:
112
+
102
113
  1. Either there is a built-in helper you don't know about (check `docs/`).
103
114
  2. Or this is a new situation — discuss it and **record** it in this document
104
115
  as one more convention.
@@ -1,22 +1,27 @@
1
1
  # Why Mado (and why not Lit / Solid / Alpine / htmx)
2
2
 
3
- > If you are choosing a frontend stack for a new project, this page is for you.
4
- > If you already have something working — **don't migrate for the sake of migration**, it always costs more than it seems.
3
+ > If you are choosing a frontend stack for an admin panel, internal tool or
4
+ > business SPA, this page is for you.
5
+ > If you already have something working — **don't migrate for the sake of
6
+ > migration**, it always costs more than it seems.
5
7
 
6
- Mado is not a "killer" of React/Vue/Svelte. It is a narrowly specialized tool. Here I honestly explain **in which cases Mado is genuinely better than the alternatives**, and in which it is not.
8
+ Mado is not a "killer" of React/Vue/Svelte. It is a focused tool for teams that
9
+ want a complete app stack (routing, forms, data, state, prerender) without
10
+ frontend infrastructure overhead. Here is an honest comparison of **when Mado is
11
+ genuinely better than the alternatives**, and when it is not.
7
12
 
8
13
  ---
9
14
 
10
15
  ## TL;DR — one table
11
16
 
12
- | If you care about… | Choose |
13
- |---|---|
14
- | Best learning infrastructure / huge ecosystem | **React** or **Vue** |
15
- | Component design system for embedding into any framework | **Lit** |
16
- | Top performance on large lists, "close to vanilla" with JSX | **Solid** or **Svelte 5** |
17
- | Progressive enhancement of classic server-rendered apps | **htmx** + your backend |
18
- | "Sprinkling" reactivity onto a static site | **Alpine.js** |
19
- | Minimal tooling, maximum platform, everything in one box (router + data + forms + SEO), readable in an evening | **Mado** ✓ |
17
+ | If you care about… | Choose |
18
+ | -------------------------------------------------------------------------------------------------------------- | ------------------------- |
19
+ | Best learning infrastructure / huge ecosystem | **React** or **Vue** |
20
+ | Component design system for embedding into any framework | **Lit** |
21
+ | Top performance on large lists, "close to vanilla" with JSX | **Solid** or **Svelte 5** |
22
+ | Progressive enhancement of classic server-rendered apps | **htmx** + your backend |
23
+ | "Sprinkling" reactivity onto a static site | **Alpine.js** |
24
+ | Minimal tooling, maximum platform, everything in one box (router + data + forms + SEO), readable in an evening | **Mado** ✓ |
20
25
 
21
26
  If your case does not fall into the last point — Mado is most likely not the best choice. That's fine.
22
27
 
@@ -26,21 +31,21 @@ If your case does not fall into the last point — Mado is most likely not the b
26
31
 
27
32
  **Lit** is the closest alternative in spirit. Same approach: Web Components + tagged templates + minimal magic.
28
33
 
29
- | | Lit | Mado |
30
- |---|---|---|
31
- | Size | ~6 KB | ~16 KB |
32
- | Age / support | ~10 years, Google | 6 months, single author |
33
- | Reactivity | `@property` decorators + manual `requestUpdate` | signals (`signal`/`computed`/`effect`) out of the box |
34
- | Router | none, you need to find one (`@lit-labs/router`, etc) | included: `routes()` + nested + prefetch + sync-cache |
35
- | Data fetching | none, you need to assemble it | `resource()` + `mutation()` + glob invalidation |
36
- | Forms | none | `useForm()` with HTML-like constraints |
37
- | SEO / static | complex (`@lit-labs/ssr`) | `bake` (linkedom) + edge-prerender |
38
- | Build | needs esbuild/rollup/webpack | `tsc` is enough |
39
- | Code style | classes + decorators | functions + tagged templates |
40
- | Ecosystem | real (Shoelace, Material Web, etc.) | none |
34
+ | | Lit | Mado |
35
+ | -------------- | -------------------------------------------------------------- | ------------------------------------------------------ |
36
+ | Size | ~6 KB | ~16 KB |
37
+ | Age / support | ~10 years, Google | 6 months, single author |
38
+ | Reactivity | `@property` decorators + manual `requestUpdate` | signals (`signal`/`computed`/`effect`) out of the box |
39
+ | Router | none, you need to find one (`@lit-labs/router`, etc) | included: `routes()` + nested + prefetch + sync-cache |
40
+ | Data fetching | none, you need to assemble it | `resource()` + `mutation()` + glob invalidation |
41
+ | Forms | none | `useForm()` with HTML-like constraints |
42
+ | SEO / static | complex (`@lit-labs/ssr`) | `bake` (linkedom) + edge-prerender |
43
+ | Build | needs esbuild/rollup/webpack | `tsc` is enough |
44
+ | Code style | classes + decorators | functions + tagged templates |
45
+ | Ecosystem | real (Shoelace, Material Web, etc.) | none |
41
46
  | When to choose | writing a design system / Web Components library for embedding | writing a full application, want everything in one box |
42
47
 
43
- **Honest pitch:** *"Lit is better if you're writing a component design system. Mado is better if you're writing an application and want batteries included without assembling 8 packages."*
48
+ **Honest pitch:** _"Lit is better if you're writing a component design system. Mado is better if you're writing an application and want batteries included without assembling 8 packages."_
44
49
 
45
50
  ---
46
51
 
@@ -48,21 +53,21 @@ If your case does not fall into the last point — Mado is most likely not the b
48
53
 
49
54
  **Solid** is a top-tier reactive library built on signals. Technically very impressive.
50
55
 
51
- | | Solid | Mado |
52
- |---|---|---|
53
- | Size | ~7 KB | ~16 KB |
54
- | Performance | top-3 on js-framework-benchmark | good, but not top |
55
- | Reactivity | signals (same class of ideas) | signals |
56
- | Templates | JSX (compiled to reactive expressions) | tagged template `html\`\`` |
57
- | Component model | functions, Solid virtual nodes | Web Components |
58
- | Build | Vite + babel-plugin-solid required | `tsc` only |
59
- | Router | `@solidjs/router` | included |
60
- | Data | `createResource` | `resource()` |
61
- | SSR | seriously supported (SolidStart) | intentionally none |
62
- | Ecosystem | growing, ~50 packages | none |
63
- | When to choose | need top performance + JSX + willing to configure the build | want to run without a build / minimal infrastructure |
64
-
65
- **Honest pitch:** *"Solid is technically faster and more mature. But Solid requires Vite + a babel plugin. Mado requires nothing but `tsc` — it's 'open VS Code, F5, and work'. If that difference isn't critical — go with Solid."*
56
+ | | Solid | Mado |
57
+ | --------------- | ----------------------------------------------------------- | ---------------------------------------------------- |
58
+ | Size | ~7 KB | ~16 KB |
59
+ | Performance | top-3 on js-framework-benchmark | good, but not top |
60
+ | Reactivity | signals (same class of ideas) | signals |
61
+ | Templates | JSX (compiled to reactive expressions) | tagged template `html\`\`` |
62
+ | Component model | functions, Solid virtual nodes | Web Components |
63
+ | Build | Vite + babel-plugin-solid required | `tsc` only |
64
+ | Router | `@solidjs/router` | included |
65
+ | Data | `createResource` | `resource()` |
66
+ | SSR | seriously supported (SolidStart) | intentionally none |
67
+ | Ecosystem | growing, ~50 packages | none |
68
+ | When to choose | need top performance + JSX + willing to configure the build | want to run without a build / minimal infrastructure |
69
+
70
+ **Honest pitch:** _"Solid is technically faster and more mature. But Solid requires Vite + a babel plugin. Mado requires nothing but `tsc` — it's 'open VS Code, F5, and work'. If that difference isn't critical — go with Solid."_
66
71
 
67
72
  ---
68
73
 
@@ -70,17 +75,17 @@ If your case does not fall into the last point — Mado is most likely not the b
70
75
 
71
76
  **Svelte 5** with runes — also a signal model, also minimalist.
72
77
 
73
- | | Svelte 5 | Mado |
74
- |---|---|---|
75
- | Runtime size | ~3 KB | ~16 KB |
76
- | Compiler | required (.svelte → JS) | none |
77
- | Syntax | custom .svelte format | TS + tagged templates |
78
- | Reactivity | `$state`/`$derived` (runes) | `signal`/`computed` |
79
- | SSR / SvelteKit | full-featured, mature | intentionally none |
80
- | Ecosystem | large, excellent dev-tools | none |
81
- | When to choose | new production project with a team | private/internal tool, need simplicity |
78
+ | | Svelte 5 | Mado |
79
+ | --------------- | ---------------------------------- | -------------------------------------- |
80
+ | Runtime size | ~3 KB | ~16 KB |
81
+ | Compiler | required (.svelte → JS) | none |
82
+ | Syntax | custom .svelte format | TS + tagged templates |
83
+ | Reactivity | `$state`/`$derived` (runes) | `signal`/`computed` |
84
+ | SSR / SvelteKit | full-featured, mature | intentionally none |
85
+ | Ecosystem | large, excellent dev-tools | none |
86
+ | When to choose | new production project with a team | private/internal tool, need simplicity |
82
87
 
83
- **Honest pitch:** *"Svelte is a product choice. Mado is an engineering one. If you have a team and a production app — Svelte. If you're alone and want control — Mado."*
88
+ **Honest pitch:** _"Svelte is a product choice. Mado is an engineering one. If you have a team and a production app — Svelte. If you're alone and want control — Mado."_
84
89
 
85
90
  ---
86
91
 
@@ -88,17 +93,17 @@ If your case does not fall into the last point — Mado is most likely not the b
88
93
 
89
94
  **htmx** is a different school: HTML-fragments over the wire.
90
95
 
91
- | | htmx | Mado |
92
- |---|---|---|
93
- | Architecture | HTML from server, updated via fragments | SPA: JS loads data, renders itself |
94
- | Backend dependency | strong (backend must be able to serve HTML) | weak (backend is a JSON API) |
95
- | Client state | minimal (cookies, localStorage) | full (signal, persisted) |
96
- | Optimistic updates | difficult | easy (mutation + invalidates) |
97
- | Offline / PWA | poor | decent |
98
- | Size | ~14 KB | ~16 KB |
99
- | When to choose | classic server-rendered app (Rails, Django, Phoenix), need to "liven up" | SPA experience is required, backend is REST/GraphQL |
96
+ | | htmx | Mado |
97
+ | ------------------ | ------------------------------------------------------------------------ | --------------------------------------------------- |
98
+ | Architecture | HTML from server, updated via fragments | SPA: JS loads data, renders itself |
99
+ | Backend dependency | strong (backend must be able to serve HTML) | weak (backend is a JSON API) |
100
+ | Client state | minimal (cookies, localStorage) | full (signal, persisted) |
101
+ | Optimistic updates | difficult | easy (mutation + invalidates) |
102
+ | Offline / PWA | poor | decent |
103
+ | Size | ~14 KB | ~16 KB |
104
+ | When to choose | classic server-rendered app (Rails, Django, Phoenix), need to "liven up" | SPA experience is required, backend is REST/GraphQL |
100
105
 
101
- **Honest pitch:** *"htmx — if the backend is solid and can serve HTML. Mado — if the backend serves JSON and you need a full SPA experience."*
106
+ **Honest pitch:** _"htmx — if the backend is solid and can serve HTML. Mado — if the backend serves JSON and you need a full SPA experience."_
102
107
 
103
108
  ---
104
109
 
@@ -106,16 +111,16 @@ If your case does not fall into the last point — Mado is most likely not the b
106
111
 
107
112
  **Alpine** — reactive attributes directly in HTML.
108
113
 
109
- | | Alpine | Mado |
110
- |---|---|---|
111
- | Purpose | enhancing static HTML | full SPA |
112
- | Size | ~7 KB | ~16 KB |
113
- | State management | `x-data` locally | signals + context + persisted |
114
- | Routing | none | included |
115
- | TypeScript | poor | first-class |
116
- | When to choose | static sites, landing pages, need 5 interactive buttons | full app: pages, navigation, forms, data |
114
+ | | Alpine | Mado |
115
+ | ---------------- | ------------------------------------------------------- | ---------------------------------------- |
116
+ | Purpose | enhancing static HTML | full SPA |
117
+ | Size | ~7 KB | ~16 KB |
118
+ | State management | `x-data` locally | signals + context + persisted |
119
+ | Routing | none | included |
120
+ | TypeScript | poor | first-class |
121
+ | When to choose | static sites, landing pages, need 5 interactive buttons | full app: pages, navigation, forms, data |
117
122
 
118
- **Honest pitch:** *"Alpine — for interactivity on static sites. Mado — for a full application."*
123
+ **Honest pitch:** _"Alpine — for interactivity on static sites. Mado — for a full application."_
119
124
 
120
125
  ---
121
126
 
@@ -124,12 +129,14 @@ If your case does not fall into the last point — Mado is most likely not the b
124
129
  I won't dwell on this for long, because React is in a **different weight class** in terms of ecosystem and maturity. But if you're seriously comparing:
125
130
 
126
131
  **React wins:**
132
+
127
133
  - massive ecosystem: thousands of UI kits, thousands of articles, endless tutorials;
128
134
  - AI assistants (ChatGPT, Copilot) know React better than anything;
129
135
  - better job market;
130
136
  - better SSR support (Next.js).
131
137
 
132
138
  **Mado wins:**
139
+
133
140
  - bundle size dozens of times smaller;
134
141
  - zero infrastructure (no Vite, no Babel, no 200 packages);
135
142
  - readable in an evening — if something breaks, open `src/`;
@@ -137,11 +144,13 @@ I won't dwell on this for long, because React is in a **different weight class**
137
144
  - no need to migrate between major versions.
138
145
 
139
146
  **When to choose Mado over React:**
147
+
140
148
  - 1–3 person project, for years to come;
141
149
  - bundle size is critical;
142
150
  - you're tired of React fatigue and are ready to sacrifice the ecosystem for simplicity.
143
151
 
144
152
  **When to choose React:**
153
+
145
154
  - team of 5 or more people;
146
155
  - you need UI kits, you need the ecosystem;
147
156
  - a project that will be hiring new people from the market;
@@ -166,6 +175,7 @@ For backend developers who are used to small, understandable libraries (chi in G
166
175
  Honestly: **Mado is not the fastest**. The top-3 on js-framework-benchmark are Solid, Inferno, and Svelte. Mado is closer to Lit / Preact in characteristics.
167
176
 
168
177
  What Mado does for performance out of the box:
178
+
169
179
  - **lazy `computed`** (dirty-flag, not eager);
170
180
  - **batch microtask scheduler** for `signal.set`;
171
181
  - **keyed reconciliation** in `each()` with real DOM reuse;