@nifrajs/web-preact 2.14.1 → 3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAkBnE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAA;AAExC,oGAAoG;AACpG,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAE/F;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAmB7D"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAkBnE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAA;AAExC,oGAAoG;AACpG,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAE/F;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAoB7D"}
package/dist/client.js CHANGED
@@ -54,6 +54,7 @@ export function mountRouter(options) {
54
54
  search: searchOfChain(searchSchemas?.[state.routeId] ?? [], rawSearch),
55
55
  // The in-flight submission (for optimistic UI) - spread only when present.
56
56
  ...(state.submission ? { submission: state.submission } : {}),
57
+ ...(state.boundaries !== undefined ? { boundaries: state.boundaries } : {}),
57
58
  });
58
59
  };
59
60
  preactHydrate(h(Router, null), container);
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,mGAAmG;AACnG,gGAAgG;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD;;;;;;GAMG;AACH,OAAO,EAA0B,CAAC,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,kGAAkG;AAClG,gGAAgG;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAA;AAExC,oGAAoG;AACpG,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB,EAAE,SAAkB;IACvF,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,SAAoB,CAAC,CAAA;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC5D,gBAAgB,CAAC,MAAM,CAAC,CAAA,CAAC,+DAA+D;IACxF,MAAM,MAAM,GAAsB,GAAG,EAAE;QACrC,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrE,uGAAuG;QACvG,uFAAuF;QACvF,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACrD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE;YAC1C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,aAAa,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;YACtE,2EAA2E;YAC3E,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,aAAa,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,SAAoB,CAAC,CAAA;AACtD,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,mGAAmG;AACnG,gGAAgG;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD;;;;;;GAMG;AACH,OAAO,EAA0B,CAAC,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,kGAAkG;AAClG,gGAAgG;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAA;AAExC,oGAAoG;AACpG,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB,EAAE,SAAkB;IACvF,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,SAAoB,CAAC,CAAA;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC5D,gBAAgB,CAAC,MAAM,CAAC,CAAA,CAAC,+DAA+D;IACxF,MAAM,MAAM,GAAsB,GAAG,EAAE;QACrC,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrE,uGAAuG;QACvG,uFAAuF;QACvF,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACrD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE;YAC1C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,aAAa,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;YACtE,2EAA2E;YAC3E,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,aAAa,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,SAAoB,CAAC,CAAA;AACtD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAgE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAA;AAejG;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,KAAK,CAoB5E"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAgE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAA;AAejG;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,KAAK,CAuB5E"}
package/dist/compose.js CHANGED
@@ -27,7 +27,10 @@ export function compose(chain, props) {
27
27
  // Each layout receives its own loader data at its own index. Layouts are the chain's leading
28
28
  // prefix, so `layoutData[i]` belongs to `chain[i]`; anything past that end (a client-only `_error`
29
29
  // boundary marker, the page) reads `undefined` and is unaffected.
30
- node = h(chain[i], { data: props.layoutData?.[i] ?? null }, node);
30
+ node = h(chain[i], {
31
+ data: props.layoutData?.[i] ?? null,
32
+ ...(props.boundaries !== undefined ? { boundaries: props.boundaries } : {}),
33
+ }, node);
31
34
  }
32
35
  return createSearchProvider(SearchContext.Provider, { value: props.search ?? EMPTY_SEARCH }, node);
33
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AACA,OAAO,EAA8C,aAAa,EAAE,CAAC,EAAc,MAAM,QAAQ,CAAA;AACjG,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,sFAAsF;AACtF,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAEzE,8FAA8F;AAC9F,oGAAoG;AACpG,0FAA0F;AAC1F,MAAM,oBAAoB,GAAG,aAInB,CAAA;AAEV;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,iGAAiG;IACjG,8FAA8F;IAC9F,mGAAmG;IACnG,gGAAgG;IAChG,2FAA2F;IAC3F,IAAI,IAAI,GAAU,CAAC,CAAC,KAAK,CAAC,IAAI,CAA+B,EAAE,KAAK,CAAU,CAAA;IAC9E,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,wFAAwF;QACxF,6FAA6F;QAC7F,mGAAmG;QACnG,kEAAkE;QAClE,IAAI,GAAG,CAAC,CACN,KAAK,CAAC,CAAC,CAAqC,EAC5C,EAAE,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EACvC,IAAI,CACI,CAAA;IACZ,CAAC;IACD,OAAO,oBAAoB,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY,EAAE,EAAE,IAAI,CAAC,CAAA;AACpG,CAAC"}
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AACA,OAAO,EAA8C,aAAa,EAAE,CAAC,EAAc,MAAM,QAAQ,CAAA;AACjG,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,sFAAsF;AACtF,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAEzE,8FAA8F;AAC9F,oGAAoG;AACpG,0FAA0F;AAC1F,MAAM,oBAAoB,GAAG,aAInB,CAAA;AAEV;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,iGAAiG;IACjG,8FAA8F;IAC9F,mGAAmG;IACnG,gGAAgG;IAChG,2FAA2F;IAC3F,IAAI,IAAI,GAAU,CAAC,CAAC,KAAK,CAAC,IAAI,CAA+B,EAAE,KAAK,CAAU,CAAA;IAC9E,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,wFAAwF;QACxF,6FAA6F;QAC7F,mGAAmG;QACnG,kEAAkE;QAClE,IAAI,GAAG,CAAC,CACN,KAAK,CAAC,CAAC,CAAqC,EAC5C;YACE,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI;YACnC,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,EACD,IAAI,CACI,CAAA;IACZ,CAAC;IACD,OAAO,oBAAoB,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY,EAAE,EAAE,IAAI,CAAC,CAAA;AACpG,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAoBvE,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAEvE;AAWD,qFAAqF;AACrF,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,qGAAqG;IACrG,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3F;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAOrD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,SAAS,OAAO,EAAE,CAKhD"}
1
+ {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAyBvE,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAEvE;AAKD,qFAAqF;AACrF,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,qGAAqG;IACrG,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3F;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAOrD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,SAAS,OAAO,EAAE,CAMhD"}
package/dist/fetcher.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMountedRouterRef, idleFetcherSnapshot, noFetchers, noopAsync, noopSubscribe, } from "@nifrajs/web/internal/fetcher-runtime";
1
2
  /**
2
3
  * `@nifrajs/web-preact/fetcher` - Preact bindings for concurrent fetchers. `useFetcher(key)` subscribes a
3
4
  * component to an independent {@link Fetcher} (via `useSyncExternalStore` from preact/compat) and
@@ -12,29 +13,19 @@
12
13
  * matches the SSR markup - no hydration mismatch.
13
14
  */
14
15
  import { useSyncExternalStore } from "preact/compat";
15
- // The active client router (set by `mountRouter`). Module-scoped: the browser mounts one app per
16
- // page, and fetchers never exist on the server. Shared with `client.ts`'s `mountRouter`.
17
- let mountedRouter;
16
+ const mountedRouter = createMountedRouterRef();
18
17
  /** Register (or clear) the router that owns fetchers - called by `mountRouter`. Not for app use. */
19
18
  export function setMountedRouter(router) {
20
- mountedRouter = router;
19
+ mountedRouter.set(router);
21
20
  }
22
- // Stable idle values for the server / pre-mount snapshot (stable refs → no `useSyncExternalStore`
23
- // loop, no hydration mismatch).
24
- const IDLE = { pending: false, data: undefined };
25
- const NO_FETCHERS = [];
26
- const noopSubscribe = () => () => { };
27
- const noopAsync = async () => { };
28
- const idleSnapshot = () => IDLE;
29
- const noFetchers = () => NO_FETCHERS;
30
21
  /**
31
22
  * Subscribe to the independent fetcher for `key` (created lazily, stable across renders). Returns its
32
23
  * state (`pending`/`data`/`actionData`/`submission`) + `load`/`submit`. Multiple `useFetcher` calls
33
24
  * with different keys run concurrently without disturbing the active route or each other.
34
25
  */
35
26
  export function useFetcher(key) {
36
- const fetcher = mountedRouter?.fetcher(key);
37
- const state = useSyncExternalStore(fetcher?.subscribe ?? noopSubscribe, fetcher?.snapshot ?? idleSnapshot);
27
+ const fetcher = mountedRouter.get()?.fetcher(key);
28
+ const state = useSyncExternalStore(fetcher?.subscribe ?? noopSubscribe, fetcher?.snapshot ?? idleFetcherSnapshot);
38
29
  return { ...state, load: fetcher?.load ?? noopAsync, submit: fetcher?.submit ?? noopAsync };
39
30
  }
40
31
  /**
@@ -43,6 +34,7 @@ export function useFetcher(key) {
43
34
  * is created.
44
35
  */
45
36
  export function useFetchers() {
46
- return useSyncExternalStore(mountedRouter?.subscribeFetchers ?? noopSubscribe, mountedRouter?.fetchers ?? noFetchers);
37
+ const router = mountedRouter.get();
38
+ return useSyncExternalStore(router?.subscribeFetchers ?? noopSubscribe, router?.fetchers ?? noFetchers);
47
39
  }
48
40
  //# sourceMappingURL=fetcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAEpD,iGAAiG;AACjG,yFAAyF;AACzF,IAAI,aAAuC,CAAA;AAE3C,oGAAoG;AACpG,MAAM,UAAU,gBAAgB,CAAC,MAAgC;IAC/D,aAAa,GAAG,MAAM,CAAA;AACxB,CAAC;AAED,kGAAkG;AAClG,gCAAgC;AAChC,MAAM,IAAI,GAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;AAC9D,MAAM,WAAW,GAAuB,EAAE,CAAA;AAC1C,MAAM,aAAa,GAAG,GAAiB,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;AAClD,MAAM,SAAS,GAAG,KAAK,IAAmB,EAAE,GAAE,CAAC,CAAA;AAC/C,MAAM,YAAY,GAAG,GAAiB,EAAE,CAAC,IAAI,CAAA;AAC7C,MAAM,UAAU,GAAG,GAAuB,EAAE,CAAC,WAAW,CAAA;AAUxD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,OAAO,GAAG,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,oBAAoB,CAChC,OAAO,EAAE,SAAS,IAAI,aAAa,EACnC,OAAO,EAAE,QAAQ,IAAI,YAAY,CAClC,CAAA;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,CAAA;AAC7F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,oBAAoB,CACzB,aAAa,EAAE,iBAAiB,IAAI,aAAa,EACjD,aAAa,EAAE,QAAQ,IAAI,UAAU,CACtC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AACA,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,aAAa,GACd,MAAM,uCAAuC,CAAA;AAC9C;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAEpD,MAAM,aAAa,GAAG,sBAAsB,EAAE,CAAA;AAE9C,oGAAoG;AACpG,MAAM,UAAU,gBAAgB,CAAC,MAAgC;IAC/D,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAC3B,CAAC;AAaD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IACjD,MAAM,KAAK,GAAG,oBAAoB,CAChC,OAAO,EAAE,SAAS,IAAI,aAAa,EACnC,OAAO,EAAE,QAAQ,IAAI,mBAAmB,CACzC,CAAA;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,CAAA;AAC7F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,CAAA;IAClC,OAAO,oBAAoB,CACzB,MAAM,EAAE,iBAAiB,IAAI,aAAa,EAC1C,MAAM,EAAE,QAAQ,IAAI,UAAU,CAC/B,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAe,UAAU,EAAE,MAAM,cAAc,CAAA;AAwBxE,wGAAwG;AACxG,wBAAgB,cAAc,IAAI,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAEvE;AAgBD,0EAA0E;AAC1E,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;IACtD,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAA;CACnC;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAejF"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAe,UAAU,EAAE,MAAM,cAAc,CAAA;AAmBxE,wGAAwG;AACxG,wBAAgB,cAAc,IAAI,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAEvE;AAOD,0EAA0E;AAC1E,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;IACtD,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAA;CACnC;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAejF"}
package/dist/query.js CHANGED
@@ -1,6 +1,4 @@
1
- // `/client`, not the root - these are DOM values, and the root's graph carries the
2
- // server, which Vite's dev server evaluates rather than tree-shakes.
3
- import { createQueryClient } from "@nifrajs/web/client";
1
+ import { createNoClientRefetch, getQueryClientSingleton, IDLE_QUERY_STATE, } from "@nifrajs/web/internal/query-runtime";
4
2
  /**
5
3
  * `@nifrajs/web-preact/query` - Preact bindings for the keyed query-cache. `useQuery(key, fn)` subscribes a
6
4
  * component to a query (via `useSyncExternalStore` from preact/compat) and fetches on mount / key change;
@@ -13,38 +11,21 @@ import { createQueryClient } from "@nifrajs/web/client";
13
11
  */
14
12
  import { useSyncExternalStore } from "preact/compat";
15
13
  import { useEffect } from "preact/hooks";
16
- let client;
17
- function getClient() {
18
- if (typeof window === "undefined")
19
- return undefined; // SSR → no client (queries render idle)
20
- if (client === undefined)
21
- client = createQueryClient({ now: () => Date.now() });
22
- return client;
23
- }
24
14
  /** Access the query client to imperatively `invalidateQueries(keyOrPrefix)` (e.g. after a mutation). */
25
15
  export function useQueryClient() {
26
- return getClient() ?? { invalidateQueries: () => { } };
16
+ return getQueryClientSingleton() ?? { invalidateQueries: () => { } };
27
17
  }
28
18
  // Stable idle snapshot for the server / pre-fetch render (stable ref → no loop, no hydration mismatch).
29
- const IDLE = Object.freeze({
30
- status: "pending",
31
- data: undefined,
32
- error: undefined,
33
- isFetching: false,
34
- updatedAt: Number.NEGATIVE_INFINITY,
35
- });
36
- const idleSnapshot = () => IDLE;
19
+ const idleSnapshot = () => IDLE_QUERY_STATE;
37
20
  const noopSubscribe = () => () => { };
38
- const noopAsync = async () => {
39
- throw new Error("[nifra/web-preact] useQuery.refetch called with no query client (server?)");
40
- };
21
+ const noopAsync = createNoClientRefetch("[nifra/web-preact]", "useQuery.refetch");
41
22
  /**
42
23
  * Subscribe to the keyed query for `key`, fetched via `fn`. Returns `{ status, data, error, isFetching,
43
24
  * updatedAt, isPending, refetch }`. Concurrent `useQuery`s with the same key share one cache entry +
44
25
  * one in-flight fetch (dedup). Refetches on mount and when the key changes; SSR-idle.
45
26
  */
46
27
  export function useQuery(key, fn) {
47
- const handle = getClient()?.query(key, fn);
28
+ const handle = getQueryClientSingleton()?.query(key, fn);
48
29
  const state = useSyncExternalStore(handle?.subscribe ?? noopSubscribe, handle ? handle.snapshot : idleSnapshot);
49
30
  // Fetch on mount + whenever the key changes (the handle is stable per key, so it changes with the key).
50
31
  useEffect(() => {
package/dist/query.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AACA,mFAAmF;AACnF,qEAAqE;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD;;;;;;;;;GASG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,IAAI,MAA+B,CAAA;AACnC,SAAS,SAAS;IAChB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,SAAS,CAAA,CAAC,wCAAwC;IAC5F,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,GAAG,iBAAiB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC/E,OAAO,MAAM,CAAA;AACf,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,cAAc;IAC5B,OAAO,SAAS,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAA;AACvD,CAAC;AAED,wGAAwG;AACxG,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,KAAK;IACjB,SAAS,EAAE,MAAM,CAAC,iBAAiB;CACpC,CAAC,CAAA;AACF,MAAM,YAAY,GAAG,GAAsB,EAAE,CAAC,IAAI,CAAA;AAClD,MAAM,aAAa,GAAG,GAAiB,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;AAClD,MAAM,SAAS,GAAG,KAAK,IAAoB,EAAE;IAC3C,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;AAC9F,CAAC,CAAA;AAUD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAI,GAAY,EAAE,EAAoB;IAC5D,MAAM,MAAM,GAA+B,SAAS,EAAE,EAAE,KAAK,CAAI,GAAG,EAAE,EAAE,CAAC,CAAA;IACzE,MAAM,KAAK,GAAG,oBAAoB,CAChC,MAAM,EAAE,SAAS,IAAI,aAAa,EAClC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CACxC,CAAA;IACD,wGAAwG;IACxG,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IAC1D,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IACZ,OAAO;QACL,GAAG,KAAK;QACR,SAAS,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS;QACrC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,SAA8B;KACnE,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,qCAAqC,CAAA;AAC5C;;;;;;;;;GASG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,wGAAwG;AACxG,MAAM,UAAU,cAAc;IAC5B,OAAO,uBAAuB,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAA;AACrE,CAAC;AAED,wGAAwG;AACxG,MAAM,YAAY,GAAG,GAAsB,EAAE,CAAC,gBAAgB,CAAA;AAC9D,MAAM,aAAa,GAAG,GAAiB,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;AAClD,MAAM,SAAS,GAAG,qBAAqB,CAAQ,oBAAoB,EAAE,kBAAkB,CAAC,CAAA;AAUxF;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAI,GAAY,EAAE,EAAoB;IAC5D,MAAM,MAAM,GAA+B,uBAAuB,EAAE,EAAE,KAAK,CAAI,GAAG,EAAE,EAAE,CAAC,CAAA;IACvF,MAAM,KAAK,GAAG,oBAAoB,CAChC,MAAM,EAAE,SAAS,IAAI,aAAa,EAClC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CACxC,CAAA;IACD,wGAAwG;IACxG,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IAC1D,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IACZ,OAAO;QACL,GAAG,KAAK;QACR,SAAS,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS;QACrC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,SAA8B;KACnE,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/web-preact",
3
- "version": "2.14.1",
3
+ "version": "3.1.0",
4
4
  "description": "Preact render adapter for @nifrajs/web - streaming SSR + hydration (no build plugin).",
5
5
  "keywords": [
6
6
  "bun",
@@ -82,10 +82,10 @@
82
82
  "access": "public"
83
83
  },
84
84
  "dependencies": {
85
- "@nifrajs/core": "2.14.1",
86
- "@nifrajs/i18n": "2.14.1",
87
- "@nifrajs/image": "2.14.1",
88
- "@nifrajs/web": "2.14.1",
85
+ "@nifrajs/core": "3.1.0",
86
+ "@nifrajs/i18n": "3.1.0",
87
+ "@nifrajs/image": "3.1.0",
88
+ "@nifrajs/web": "3.1.0",
89
89
  "preact-render-to-string": "^6.5.0"
90
90
  },
91
91
  "peerDependencies": {
package/src/client.ts CHANGED
@@ -59,6 +59,7 @@ export function mountRouter(options: MountRouterOptions): void {
59
59
  search: searchOfChain(searchSchemas?.[state.routeId] ?? [], rawSearch),
60
60
  // The in-flight submission (for optimistic UI) - spread only when present.
61
61
  ...(state.submission ? { submission: state.submission } : {}),
62
+ ...(state.boundaries !== undefined ? { boundaries: state.boundaries } : {}),
62
63
  })
63
64
  }
64
65
  preactHydrate(h(Router, null), container as Element)
package/src/compose.ts CHANGED
@@ -37,7 +37,10 @@ export function compose(chain: readonly unknown[], props: RenderProps): VNode {
37
37
  // boundary marker, the page) reads `undefined` and is unaffected.
38
38
  node = h(
39
39
  chain[i] as ComponentType<{ data: unknown }>,
40
- { data: props.layoutData?.[i] ?? null },
40
+ {
41
+ data: props.layoutData?.[i] ?? null,
42
+ ...(props.boundaries !== undefined ? { boundaries: props.boundaries } : {}),
43
+ },
41
44
  node,
42
45
  ) as VNode
43
46
  }
package/src/fetcher.ts CHANGED
@@ -1,4 +1,11 @@
1
1
  import type { ClientRouter, Fetcher, FetcherState } from "@nifrajs/web"
2
+ import {
3
+ createMountedRouterRef,
4
+ idleFetcherSnapshot,
5
+ noFetchers,
6
+ noopAsync,
7
+ noopSubscribe,
8
+ } from "@nifrajs/web/internal/fetcher-runtime"
2
9
  /**
3
10
  * `@nifrajs/web-preact/fetcher` - Preact bindings for concurrent fetchers. `useFetcher(key)` subscribes a
4
11
  * component to an independent {@link Fetcher} (via `useSyncExternalStore` from preact/compat) and
@@ -14,23 +21,15 @@ import type { ClientRouter, Fetcher, FetcherState } from "@nifrajs/web"
14
21
  */
15
22
  import { useSyncExternalStore } from "preact/compat"
16
23
 
17
- // The active client router (set by `mountRouter`). Module-scoped: the browser mounts one app per
18
- // page, and fetchers never exist on the server. Shared with `client.ts`'s `mountRouter`.
19
- let mountedRouter: ClientRouter | undefined
24
+ const mountedRouter = createMountedRouterRef()
20
25
 
21
26
  /** Register (or clear) the router that owns fetchers - called by `mountRouter`. Not for app use. */
22
27
  export function setMountedRouter(router: ClientRouter | undefined): void {
23
- mountedRouter = router
28
+ mountedRouter.set(router)
24
29
  }
25
30
 
26
31
  // Stable idle values for the server / pre-mount snapshot (stable refs → no `useSyncExternalStore`
27
32
  // loop, no hydration mismatch).
28
- const IDLE: FetcherState = { pending: false, data: undefined }
29
- const NO_FETCHERS: readonly Fetcher[] = []
30
- const noopSubscribe = (): (() => void) => () => {}
31
- const noopAsync = async (): Promise<void> => {}
32
- const idleSnapshot = (): FetcherState => IDLE
33
- const noFetchers = (): readonly Fetcher[] => NO_FETCHERS
34
33
 
35
34
  /** A fetcher's reactive {@link FetcherState} plus its imperative `load`/`submit`. */
36
35
  export interface FetcherHandle extends FetcherState {
@@ -46,10 +45,10 @@ export interface FetcherHandle extends FetcherState {
46
45
  * with different keys run concurrently without disturbing the active route or each other.
47
46
  */
48
47
  export function useFetcher(key: string): FetcherHandle {
49
- const fetcher = mountedRouter?.fetcher(key)
48
+ const fetcher = mountedRouter.get()?.fetcher(key)
50
49
  const state = useSyncExternalStore(
51
50
  fetcher?.subscribe ?? noopSubscribe,
52
- fetcher?.snapshot ?? idleSnapshot,
51
+ fetcher?.snapshot ?? idleFetcherSnapshot,
53
52
  )
54
53
  return { ...state, load: fetcher?.load ?? noopAsync, submit: fetcher?.submit ?? noopAsync }
55
54
  }
@@ -60,8 +59,9 @@ export function useFetcher(key: string): FetcherHandle {
60
59
  * is created.
61
60
  */
62
61
  export function useFetchers(): readonly Fetcher[] {
62
+ const router = mountedRouter.get()
63
63
  return useSyncExternalStore(
64
- mountedRouter?.subscribeFetchers ?? noopSubscribe,
65
- mountedRouter?.fetchers ?? noFetchers,
64
+ router?.subscribeFetchers ?? noopSubscribe,
65
+ router?.fetchers ?? noFetchers,
66
66
  )
67
67
  }
package/src/query.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { QueryClient, QueryHandle, QueryState } from "@nifrajs/web"
2
- // `/client`, not the root - these are DOM values, and the root's graph carries the
3
- // server, which Vite's dev server evaluates rather than tree-shakes.
4
- import { createQueryClient } from "@nifrajs/web/client"
2
+ import {
3
+ createNoClientRefetch,
4
+ getQueryClientSingleton,
5
+ IDLE_QUERY_STATE,
6
+ } from "@nifrajs/web/internal/query-runtime"
5
7
  /**
6
8
  * `@nifrajs/web-preact/query` - Preact bindings for the keyed query-cache. `useQuery(key, fn)` subscribes a
7
9
  * component to a query (via `useSyncExternalStore` from preact/compat) and fetches on mount / key change;
@@ -15,31 +17,15 @@ import { createQueryClient } from "@nifrajs/web/client"
15
17
  import { useSyncExternalStore } from "preact/compat"
16
18
  import { useEffect } from "preact/hooks"
17
19
 
18
- let client: QueryClient | undefined
19
- function getClient(): QueryClient | undefined {
20
- if (typeof window === "undefined") return undefined // SSR → no client (queries render idle)
21
- if (client === undefined) client = createQueryClient({ now: () => Date.now() })
22
- return client
23
- }
24
-
25
20
  /** Access the query client to imperatively `invalidateQueries(keyOrPrefix)` (e.g. after a mutation). */
26
21
  export function useQueryClient(): Pick<QueryClient, "invalidateQueries"> {
27
- return getClient() ?? { invalidateQueries: () => {} }
22
+ return getQueryClientSingleton() ?? { invalidateQueries: () => {} }
28
23
  }
29
24
 
30
25
  // Stable idle snapshot for the server / pre-fetch render (stable ref → no loop, no hydration mismatch).
31
- const IDLE: QueryState<never> = Object.freeze({
32
- status: "pending",
33
- data: undefined,
34
- error: undefined,
35
- isFetching: false,
36
- updatedAt: Number.NEGATIVE_INFINITY,
37
- })
38
- const idleSnapshot = (): QueryState<never> => IDLE
26
+ const idleSnapshot = (): QueryState<never> => IDLE_QUERY_STATE
39
27
  const noopSubscribe = (): (() => void) => () => {}
40
- const noopAsync = async (): Promise<never> => {
41
- throw new Error("[nifra/web-preact] useQuery.refetch called with no query client (server?)")
42
- }
28
+ const noopAsync = createNoClientRefetch<never>("[nifra/web-preact]", "useQuery.refetch")
43
29
 
44
30
  /** A query's reactive {@link QueryState} plus `isPending` + `refetch`. */
45
31
  export interface UseQueryResult<T> extends QueryState<T> {
@@ -55,7 +41,7 @@ export interface UseQueryResult<T> extends QueryState<T> {
55
41
  * one in-flight fetch (dedup). Refetches on mount and when the key changes; SSR-idle.
56
42
  */
57
43
  export function useQuery<T>(key: unknown, fn: () => Promise<T>): UseQueryResult<T> {
58
- const handle: QueryHandle<T> | undefined = getClient()?.query<T>(key, fn)
44
+ const handle: QueryHandle<T> | undefined = getQueryClientSingleton()?.query<T>(key, fn)
59
45
  const state = useSyncExternalStore<QueryState<T>>(
60
46
  handle?.subscribe ?? noopSubscribe,
61
47
  handle ? handle.snapshot : idleSnapshot,