@nifrajs/web-solid 5.8.0 → 5.10.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.
- package/CHANGELOG.md +104 -0
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +3 -1
- package/dist/compose.js.map +1 -1
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +2 -1
- package/dist/fn.js.map +1 -1
- package/dist/image.d.ts +4 -3
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +16 -6
- package/dist/image.js.map +1 -1
- package/dist/keep-alive.d.ts +1 -1
- package/dist/keep-alive.d.ts.map +1 -1
- package/dist/keep-alive.js +6 -14
- package/dist/keep-alive.js.map +1 -1
- package/dist/ppr.d.ts +2 -10
- package/dist/ppr.d.ts.map +1 -1
- package/dist/ppr.js +1 -1
- package/dist/ppr.js.map +1 -1
- package/dist/query.d.ts +43 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +73 -5
- package/dist/query.js.map +1 -1
- package/dist/router.d.ts +2 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +5 -9
- package/dist/router.js.map +1 -1
- package/package.json +5 -5
- package/src/compose.ts +3 -1
- package/src/fn.ts +3 -2
- package/src/image.ts +28 -7
- package/src/keep-alive.ts +7 -20
- package/src/ppr.ts +2 -11
- package/src/query.ts +145 -6
- package/src/router.ts +6 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,109 @@
|
|
|
1
1
|
# @nifrajs/web-solid
|
|
2
2
|
|
|
3
|
+
## 5.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 611a3be: Expose mutation and infinite-query bindings across the framework adapters, with request-scoped query-client providers and SSR cache hydration. Mutation functions and callbacks receive a cooperative abort signal, and identity changes cancel pending work across tabs. `dehydrate` can filter regular and infinite query values before they are serialized to the browser.
|
|
8
|
+
- d2066e0: Add opt-in local `?image` metadata imports and content-hashed build-time responsive variants using the existing injectable image backends. Emit images with client, SSR and static builds, and infer imported dimensions in all five UI adapters. String image URLs retain their existing dimension requirements.
|
|
9
|
+
|
|
10
|
+
Add explicit static translated-path mappings to i18n routing, with reciprocal URL/SEO helpers, availability-aware redirects and static-path enumeration. These mappings do not implicitly create filesystem route aliases.
|
|
11
|
+
|
|
12
|
+
Add `vercelRuntime: "node"` for ordinary SSR Vercel builds through both bundlers, using a shared streaming Node request bridge. Vercel Edge remains the default.
|
|
13
|
+
- 824a75e: Partial prerendering is no longer experimental. `createWebApp` takes it as `ppr`, where it was `experimental.ppr`, and the `experimental` option is gone: passing it throws a `TypeError` that names `ppr`, and the startup errors name `ppr.origin`, `ppr.deployment` and `ppr.store`. `nifra upgrade` moves `experimental: { ppr }` to `ppr` in a `createWebApp` options literal and lists any other `experimental` shape it finds there by line (options spread in, or built in another file, are yours to check). `nifra scaffold` is stable.
|
|
14
|
+
- 1faf86c: `href({ to, params, search, hash })` builds an in-app URL from a route pattern and returns an `Href`; `rawHref(path)` returns one for a same-origin path built elsewhere (a CMS link, `/llms.txt`). `to` is a key of the generated `RouteTable`, so a misspelt route, a missing, misspelt or extra param, and a `search` that breaks the route's schema are compile errors. A route without a `searchSchema` takes any `search`. Each param is encoded as one path segment, so a value such as `a/b` or `//evil.com` cannot change where the URL goes; a param that is missing, empty, `.`, `..` or an unpaired surrogate throws a `TypeError` naming it and the pattern. `rawHref` throws a `TypeError` unless `isSameOriginPath` accepts the path. Both are exported by `@nifrajs/web` and by the `/router` entry of every adapter.
|
|
15
|
+
|
|
16
|
+
`navigate` takes an `Href` or a history delta. A string, a template literal and the `{ to, search }` object form are compile errors, and a value forged past the types is still held to the same-origin check the browser navigate makes. `<Navigate to>` and the `useSearchParams` setter in `@nifrajs/web-react` pass their path through `rawHref`, so an off-origin `to` throws instead of doing nothing. `isSameOriginPath` is exported from `@nifrajs/core/pattern` as well as `@nifrajs/core/server`.
|
|
17
|
+
|
|
18
|
+
Upgrade: `navigate("/users/7")` becomes `navigate(href({ to: "/users/:id", params: { id: "7" } }))`, `navigate({ to, search, replace: true })` becomes `navigate(href({ to, search }), { replace: true })`, and a path built elsewhere is `navigate(rawHref(path))`. `resolveNavigate`, `NavigateTargetInput` and `NavigateSearchOf` are removed from `@nifrajs/web`.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 2c361be: Opening a modal route on a Solid page no longer rebuilds the page. A layout was handed the `boundaries` value rather than a getter over it, so an intercept boundary taking its target re-ran the whole chain: a typed input lost its text and every component remounted. The page now stays mounted underneath, as the other adapters keep it.
|
|
23
|
+
- Updated dependencies [535c4e5]
|
|
24
|
+
- Updated dependencies [87e7fd9]
|
|
25
|
+
- Updated dependencies [611a3be]
|
|
26
|
+
- Updated dependencies [7f32bb2]
|
|
27
|
+
- Updated dependencies [0aa10d0]
|
|
28
|
+
- Updated dependencies [ab69ee6]
|
|
29
|
+
- Updated dependencies [548bade]
|
|
30
|
+
- Updated dependencies [d2066e0]
|
|
31
|
+
- Updated dependencies [7e292dd]
|
|
32
|
+
- Updated dependencies [a6af4c9]
|
|
33
|
+
- Updated dependencies [e465ed5]
|
|
34
|
+
- Updated dependencies [683c3d6]
|
|
35
|
+
- Updated dependencies [824a75e]
|
|
36
|
+
- Updated dependencies [d2066e0]
|
|
37
|
+
- Updated dependencies [5845e1c]
|
|
38
|
+
- Updated dependencies [5d1be78]
|
|
39
|
+
- Updated dependencies [1faf86c]
|
|
40
|
+
- Updated dependencies [950996b]
|
|
41
|
+
- @nifrajs/web@5.10.0
|
|
42
|
+
- @nifrajs/core@5.10.0
|
|
43
|
+
|
|
44
|
+
## 5.9.0
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- 2ffa7c1: The React, Preact, Solid, Svelte and Vue `useServerFn` bindings take their function through one shared helper in `@nifrajs/web/internal/client-server-fn`.
|
|
49
|
+
|
|
50
|
+
The React, Svelte and Vue client and keep-alive mounts read a hydration verification runner's hooks through one reader in `@nifrajs/web/internal/hydration-assurance`. Recoverable errors and warnings reach the runner as before.
|
|
51
|
+
- 71dea89: Every binding's `useNavigate` returns one navigate from `@nifrajs/web/internal/navigate-runtime`, the same function on every call. The React, Preact, Solid and Vue `Hole` components read their boundary state through the `HoleState` type in `@nifrajs/web/internal/hole-runtime`.
|
|
52
|
+
- a0fe5bf: The keep-alive mounts of the React, Preact, Svelte, Solid and Vue adapters take their framework-free half from `@nifrajs/web/internal/keep-alive-mount`. This covers the slot tree of each router state, the parking each committed tree goes to, render props made once per state, and the slots under each layout. Each adapter still renders the slots its own way. Kept pages behave as before.
|
|
53
|
+
- Updated dependencies [2ffa7c1]
|
|
54
|
+
- Updated dependencies [100a0aa]
|
|
55
|
+
- Updated dependencies [71dea89]
|
|
56
|
+
- Updated dependencies [9c20e05]
|
|
57
|
+
- Updated dependencies [9942748]
|
|
58
|
+
- Updated dependencies [8cdb138]
|
|
59
|
+
- Updated dependencies [be1c677]
|
|
60
|
+
- Updated dependencies [f399e06]
|
|
61
|
+
- Updated dependencies [93e7078]
|
|
62
|
+
- Updated dependencies [2c2f58b]
|
|
63
|
+
- Updated dependencies [123409c]
|
|
64
|
+
- Updated dependencies [7ee17d0]
|
|
65
|
+
- Updated dependencies [68d9f31]
|
|
66
|
+
- Updated dependencies [fa7d102]
|
|
67
|
+
- Updated dependencies [ddeb735]
|
|
68
|
+
- Updated dependencies [a3fb195]
|
|
69
|
+
- Updated dependencies [47a864f]
|
|
70
|
+
- Updated dependencies [9942748]
|
|
71
|
+
- Updated dependencies [ffcf41a]
|
|
72
|
+
- Updated dependencies [7a15327]
|
|
73
|
+
- Updated dependencies [866c8ec]
|
|
74
|
+
- Updated dependencies [bc42fd2]
|
|
75
|
+
- Updated dependencies [a29d1cc]
|
|
76
|
+
- Updated dependencies [9942748]
|
|
77
|
+
- Updated dependencies [77b98ea]
|
|
78
|
+
- Updated dependencies [a3caf9b]
|
|
79
|
+
- Updated dependencies [a0fe5bf]
|
|
80
|
+
- Updated dependencies [7ba5c9b]
|
|
81
|
+
- Updated dependencies [0445564]
|
|
82
|
+
- Updated dependencies [180bf9d]
|
|
83
|
+
- Updated dependencies [ff9bc11]
|
|
84
|
+
- Updated dependencies [8094874]
|
|
85
|
+
- Updated dependencies [a7b89ee]
|
|
86
|
+
- Updated dependencies [34b780e]
|
|
87
|
+
- Updated dependencies [111c3be]
|
|
88
|
+
- Updated dependencies [5bd225e]
|
|
89
|
+
- Updated dependencies [d6e6617]
|
|
90
|
+
- Updated dependencies [5bc60b7]
|
|
91
|
+
- Updated dependencies [159ae97]
|
|
92
|
+
- Updated dependencies [6ba9740]
|
|
93
|
+
- Updated dependencies [5f4416a]
|
|
94
|
+
- Updated dependencies [bc05ec5]
|
|
95
|
+
- Updated dependencies [d3c050e]
|
|
96
|
+
- Updated dependencies [c4ed3e9]
|
|
97
|
+
- Updated dependencies [9942748]
|
|
98
|
+
- Updated dependencies [5bc60b7]
|
|
99
|
+
- Updated dependencies [3299474]
|
|
100
|
+
- Updated dependencies [543d00a]
|
|
101
|
+
- Updated dependencies [020eb7b]
|
|
102
|
+
- Updated dependencies [9942748]
|
|
103
|
+
- Updated dependencies [9785cd4]
|
|
104
|
+
- @nifrajs/web@5.9.0
|
|
105
|
+
- @nifrajs/core@5.9.0
|
|
106
|
+
|
|
3
107
|
## 5.8.0
|
|
4
108
|
|
|
5
109
|
### Patch Changes
|
package/dist/compose.d.ts.map
CHANGED
|
@@ -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,EAAmC,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAMpE;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,CAAC,OAAO,
|
|
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,EAAmC,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAMpE;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,CAAC,OAAO,CAqCxF"}
|
package/dist/compose.js
CHANGED
|
@@ -25,7 +25,9 @@ export function compose(chain, props) {
|
|
|
25
25
|
get data() {
|
|
26
26
|
return props.layoutData?.[i] ?? null;
|
|
27
27
|
},
|
|
28
|
-
|
|
28
|
+
get boundaries() {
|
|
29
|
+
return props.boundaries;
|
|
30
|
+
},
|
|
29
31
|
children: child(),
|
|
30
32
|
});
|
|
31
33
|
}
|
package/dist/compose.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,eAAe,EAAY,MAAM,UAAU,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE/D,sFAAsF;AACtF,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAEzE;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,IAAI,IAAI,GAAsB,GAAG,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAA2B,EAAE,KAAK,CAAC,CAAA;IACjG,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAyC,CAAA;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAA;QAClB,6FAA6F;QAC7F,mGAAmG;QACnG,kEAAkE;QAClE,0FAA0F;QAC1F,6EAA6E;QAC7E,IAAI,GAAG,GAAG,EAAE,CACV,eAAe,CAAC,MAAM,EAAE;YACtB,IAAI,IAAI;gBACN,OAAO,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;YACtC,CAAC;YACD,
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,eAAe,EAAY,MAAM,UAAU,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE/D,sFAAsF;AACtF,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAEzE;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,IAAI,IAAI,GAAsB,GAAG,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAA2B,EAAE,KAAK,CAAC,CAAA;IACjG,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAyC,CAAA;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAA;QAClB,6FAA6F;QAC7F,mGAAmG;QACnG,kEAAkE;QAClE,0FAA0F;QAC1F,6EAA6E;QAC7E,IAAI,GAAG,GAAG,EAAE,CACV,eAAe,CAAC,MAAM,EAAE;YACtB,IAAI,IAAI;gBACN,OAAO,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;YACtC,CAAC;YACD,IAAI,UAAU;gBACZ,OAAO,KAAK,CAAC,UAAU,CAAA;YACzB,CAAC;YACD,QAAQ,EAAE,KAAK,EAAE;SAClB,CAAC,CAAA;IACN,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAA;IAClB,qGAAqG;IACrG,sFAAsF;IACtF,OAAO,GAAG,EAAE,CACV,eAAe,CAAC,aAAa,CAAC,QAAQ,EAAE;QACtC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,YAAY,CAA4B;QACtE,IAAI,QAAQ;YACV,OAAO,eAAe,CAAC,kBAAkB,CAAC,QAAQ,EAAE;gBAClD,KAAK,EAAE,KAAK;gBACZ,IAAI,QAAQ;oBACV,OAAO,KAAK,EAAE,CAAA;gBAChB,CAAC;aACF,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;AACN,CAAC"}
|
package/dist/fn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fn.d.ts","sourceRoot":"","sources":["../src/fn.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"fn.d.ts","sourceRoot":"","sources":["../src/fn.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE/E,OAAO,EAAE,KAAK,QAAQ,EAA2B,MAAM,UAAU,CAAA;AAEjE,+DAA+D;AAC/D,MAAM,WAAW,cAAc,CAAC,KAAK,EAAE,MAAM;IAC3C,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;IAC/C,mGAAmG;IACnG,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAChD,oBAAoB;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EACvC,EAAE,EAAE,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,GACnC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAS/B"}
|
package/dist/fn.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* "is it pending" has one answer rather than five that drift. This file contributes only a signal fed by the store.
|
|
9
9
|
*/
|
|
10
10
|
import { createServerFnStore } from "@nifrajs/web/fn-state";
|
|
11
|
+
import { clientServerFn } from "@nifrajs/web/internal/client-server-fn";
|
|
11
12
|
import { createSignal, onCleanup } from "solid-js";
|
|
12
13
|
/**
|
|
13
14
|
* Track one server function's call state.
|
|
@@ -16,7 +17,7 @@ import { createSignal, onCleanup } from "solid-js";
|
|
|
16
17
|
* <button disabled={addTodo.state().pending} onClick={() => addTodo.call({ text }).catch(() => {})}>
|
|
17
18
|
*/
|
|
18
19
|
export function useServerFn(fn) {
|
|
19
|
-
const store = createServerFnStore(fn);
|
|
20
|
+
const store = createServerFnStore(clientServerFn(fn));
|
|
20
21
|
// Seeded from the store, not from the idle constant. They are the same value here - the store is
|
|
21
22
|
// created one line up and cannot have moved - so this is correctness that does not depend on that
|
|
22
23
|
// staying true. Svelte had exactly this line reading the constant, and when its subscription turned
|
package/dist/fn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fn.js","sourceRoot":"","sources":["../src/fn.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,mBAAmB,EAAsB,MAAM,uBAAuB,CAAA;AAC/E,OAAO,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAYjE;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,EAAoC;IAEpC,MAAM,KAAK,GAAG,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"fn.js","sourceRoot":"","sources":["../src/fn.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,mBAAmB,EAAsB,MAAM,uBAAuB,CAAA;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AACvE,OAAO,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAYjE;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,EAAoC;IAEpC,MAAM,KAAK,GAAG,mBAAmB,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAA;IACrD,iGAAiG;IACjG,kGAAkG;IAClG,oGAAoG;IACpG,oFAAoF;IACpF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAwB,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC/E,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAA;IAClE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAA;AACxD,CAAC"}
|
package/dist/image.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* reactively (`splitProps`/`mergeProps`). Resizing is delegated to the `loader`; nifra bundles no codec.
|
|
7
7
|
* No JSX (`createComponent`/`Dynamic`), so the package builds with plain `tsc`.
|
|
8
8
|
*/
|
|
9
|
-
import { type ImageLoader, type ImageProps } from "@nifrajs/image";
|
|
9
|
+
import { type ImageLoader, type ImageProps, type StaticImageProps } from "@nifrajs/image";
|
|
10
10
|
import { type JSX } from "solid-js";
|
|
11
11
|
/** Attributes `resolveImage` computes - callers can't override them via DOM passthrough. */
|
|
12
12
|
type ComputedAttrs = "src" | "srcset" | "sizes" | "width" | "height" | "alt" | "loading" | "decoding" | "fetchpriority";
|
|
@@ -14,10 +14,11 @@ export interface ImageComponentProps extends ImageProps, Omit<JSX.ImgHTMLAttribu
|
|
|
14
14
|
/** CDN URL builder. Defaults to the identity loader (no transform - still CLS-safe + lazy). */
|
|
15
15
|
readonly loader?: ImageLoader;
|
|
16
16
|
}
|
|
17
|
+
export type StaticImageComponentProps = StaticImageProps & Omit<ImageComponentProps, "src" | "width" | "height">;
|
|
17
18
|
/**
|
|
18
|
-
* Render a responsive, CLS-safe `<img>`.
|
|
19
|
+
* Render a responsive, CLS-safe `<img>`. String URLs require dimensions; asset imports infer them;
|
|
19
20
|
* `priority` marks the LCP image (`eager` + `fetchpriority="high"`). Extra DOM props pass through.
|
|
20
21
|
*/
|
|
21
|
-
export declare function Image(props: ImageComponentProps): JSX.Element;
|
|
22
|
+
export declare function Image(props: ImageComponentProps | StaticImageComponentProps): JSX.Element;
|
|
22
23
|
export {};
|
|
23
24
|
//# sourceMappingURL=image.d.ts.map
|
package/dist/image.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,UAAU,EAEf,KAAK,gBAAgB,EAEtB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAmB,KAAK,GAAG,EAA0B,MAAM,UAAU,CAAA;AAG5E,4FAA4F;AAC5F,KAAK,aAAa,GACd,KAAK,GACL,QAAQ,GACR,OAAO,GACP,OAAO,GACP,QAAQ,GACR,KAAK,GACL,SAAS,GACT,UAAU,GACV,eAAe,CAAA;AAEnB,MAAM,WAAW,mBACf,SAAQ,UAAU,EAChB,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,aAAa,GAAG,MAAM,UAAU,CAAC;IACjF,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED,MAAM,MAAM,yBAAyB,GAAG,gBAAgB,GACtD,IAAI,CAAC,mBAAmB,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAA;AAEvD;;;GAGG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,yBAAyB,GAAG,GAAG,CAAC,OAAO,CA2CzF"}
|
package/dist/image.js
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
* reactively (`splitProps`/`mergeProps`). Resizing is delegated to the `loader`; nifra bundles no codec.
|
|
7
7
|
* No JSX (`createComponent`/`Dynamic`), so the package builds with plain `tsc`.
|
|
8
8
|
*/
|
|
9
|
-
import { resolveImage, toHtmlAttrs } from "@nifrajs/image";
|
|
9
|
+
import { resolveImage, toHtmlAttrs, } from "@nifrajs/image";
|
|
10
10
|
import { createComponent, mergeProps, splitProps } from "solid-js";
|
|
11
11
|
import { Dynamic } from "solid-js/web";
|
|
12
12
|
/**
|
|
13
|
-
* Render a responsive, CLS-safe `<img>`.
|
|
13
|
+
* Render a responsive, CLS-safe `<img>`. String URLs require dimensions; asset imports infer them;
|
|
14
14
|
* `priority` marks the LCP image (`eager` + `fetchpriority="high"`). Extra DOM props pass through.
|
|
15
15
|
*/
|
|
16
16
|
export function Image(props) {
|
|
@@ -31,10 +31,7 @@ export function Image(props) {
|
|
|
31
31
|
const attrs = () => {
|
|
32
32
|
// Build ImageProps via conditional spreads (exactOptionalPropertyTypes: an unset optional is
|
|
33
33
|
// absent, not `undefined`). resolveImage validates width/height > 0 (CLS contract).
|
|
34
|
-
const
|
|
35
|
-
src: props.src,
|
|
36
|
-
width: props.width,
|
|
37
|
-
height: props.height,
|
|
34
|
+
const common = {
|
|
38
35
|
alt: props.alt,
|
|
39
36
|
...(props.sizes !== undefined ? { sizes: props.sizes } : {}),
|
|
40
37
|
...(props.widths !== undefined ? { widths: props.widths } : {}),
|
|
@@ -42,6 +39,19 @@ export function Image(props) {
|
|
|
42
39
|
...(props.loading !== undefined ? { loading: props.loading } : {}),
|
|
43
40
|
...(props.priority !== undefined ? { priority: props.priority } : {}),
|
|
44
41
|
};
|
|
42
|
+
const input = typeof props.src === "string"
|
|
43
|
+
? {
|
|
44
|
+
...common,
|
|
45
|
+
src: props.src,
|
|
46
|
+
width: props.width ?? Number.NaN,
|
|
47
|
+
height: props.height ?? Number.NaN,
|
|
48
|
+
}
|
|
49
|
+
: {
|
|
50
|
+
...common,
|
|
51
|
+
src: props.src,
|
|
52
|
+
...(props.width !== undefined ? { width: props.width } : {}),
|
|
53
|
+
...(props.height !== undefined ? { height: props.height } : {}),
|
|
54
|
+
};
|
|
45
55
|
return toHtmlAttrs(resolveImage(input, props.loader));
|
|
46
56
|
};
|
|
47
57
|
return createComponent(Dynamic, mergeProps(rest, attrs, { component: "img" }));
|
package/dist/image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAIL,YAAY,EAEZ,WAAW,GACZ,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,eAAe,EAAY,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAwBtC;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,KAAsD;IAC1E,sGAAsG;IACtG,iGAAiG;IACjG,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE;QACjC,QAAQ;QACR,QAAQ;QACR,SAAS;QACT,UAAU;QACV,KAAK;QACL,OAAO;QACP,QAAQ;QACR,KAAK;QACL,OAAO;QACP,SAAS;KACV,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,GAAmC,EAAE;QACjD,6FAA6F;QAC7F,oFAAoF;QACpF,MAAM,MAAM,GAAG;YACb,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtE,CAAA;QACD,MAAM,KAAK,GACT,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;YAC3B,CAAC,CAAC;gBACE,GAAG,MAAM;gBACT,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG;gBAChC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,GAAG;aACnC;YACH,CAAC,CAAC;gBACE,GAAG,MAAM;gBACT,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChE,CAAA;QACP,OAAO,WAAW,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IACvD,CAAC,CAAA;IACD,OAAO,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AAChF,CAAC"}
|
package/dist/keep-alive.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* in place, synchronously, so the DOM half runs right after each publish.
|
|
10
10
|
*/
|
|
11
11
|
import type { MountRouterOptions } from "@nifrajs/web";
|
|
12
|
-
import {
|
|
12
|
+
import type { KeepAliveRouter, KeepAliveTable } from "@nifrajs/web/keep-alive";
|
|
13
13
|
export * from "./client.js";
|
|
14
14
|
export { onPageHide, onPageShow, usePageVisibility } from "./page-visibility.js";
|
|
15
15
|
/** `mountRouter`'s options in a keep-alive app: the generated entry adds where the wrappers go. */
|
package/dist/keep-alive.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keep-alive.d.ts","sourceRoot":"","sources":["../src/keep-alive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"keep-alive.d.ts","sourceRoot":"","sources":["../src/keep-alive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,cAAc,CAAA;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAY,MAAM,yBAAyB,CAAA;AAOxF,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAEhF,mGAAmG;AACnG,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;CACnC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CA8BhE"}
|
package/dist/keep-alive.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { keptMount } from "@nifrajs/web/internal/keep-alive-mount";
|
|
2
2
|
import { createMemo, createSignal } from "solid-js";
|
|
3
3
|
import { hydrate as solidHydrate } from "solid-js/web";
|
|
4
4
|
import { setMountedRouter } from "./fetcher.js";
|
|
@@ -11,37 +11,29 @@ export { onPageHide, onPageShow, usePageVisibility } from "./page-visibility.js"
|
|
|
11
11
|
* wrappers the server rendered), so hydration claims the document as it is.
|
|
12
12
|
*/
|
|
13
13
|
export function mountRouter(options) {
|
|
14
|
-
const { router,
|
|
14
|
+
const { router, searchSchemas, container } = options;
|
|
15
15
|
const matchChains = options.matchChains ?? {};
|
|
16
16
|
setMountedRouter(router);
|
|
17
|
-
const
|
|
18
|
-
let committed;
|
|
19
|
-
router.beforePublish((next) => parking.before(slotTree(next, matchChains, table, committed)));
|
|
17
|
+
const kept = keptMount(options);
|
|
20
18
|
let current = [];
|
|
21
19
|
let publish;
|
|
22
|
-
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: the generated entry passes the element the server rendered the app into
|
|
23
20
|
solidHydrate(() => {
|
|
24
21
|
const [state, setState] = createSignal(router.snapshot());
|
|
25
22
|
publish = (next) => setState(() => next);
|
|
26
23
|
const tree = createMemo(() => {
|
|
27
|
-
current =
|
|
24
|
+
current = kept.tree(state(), current);
|
|
28
25
|
return current;
|
|
29
26
|
});
|
|
30
27
|
const mount = {
|
|
28
|
+
...kept,
|
|
31
29
|
propsOf: (of) => routeProps(of, searchSchemas, matchChains, (read) => createMemo(read)),
|
|
32
|
-
chainOf: (of) => routes[of.routeId] ?? [],
|
|
33
|
-
entry: parking.entry,
|
|
34
|
-
page: parking.page,
|
|
35
30
|
};
|
|
36
31
|
return KeepAliveView({ tree, shown: mount.propsOf(state), mount });
|
|
37
32
|
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: the generated entry passes the element the server rendered the app into
|
|
38
33
|
}, container);
|
|
39
34
|
// Solid has updated the document by the time a publish returns: park what it hid, restore what it
|
|
40
35
|
// showed again.
|
|
41
|
-
const after = () =>
|
|
42
|
-
committed = current;
|
|
43
|
-
parking.after(current);
|
|
44
|
-
};
|
|
36
|
+
const after = () => kept.after(current);
|
|
45
37
|
after();
|
|
46
38
|
router.subscribe(() => {
|
|
47
39
|
publish?.(router.snapshot());
|
package/dist/keep-alive.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keep-alive.js","sourceRoot":"","sources":["../src/keep-alive.ts"],"names":[],"mappings":"AAWA,OAAO,
|
|
1
|
+
{"version":3,"file":"keep-alive.js","sourceRoot":"","sources":["../src/keep-alive.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAElE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAA2B,MAAM,sBAAsB,CAAA;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAQhF;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAA8B;IACxD,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IACpD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE,CAAA;IAC7C,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACxB,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;IAE/B,IAAI,OAAO,GAAwB,EAAE,CAAA;IACrC,IAAI,OAAmD,CAAA;IACvD,YAAY,CAAC,GAAG,EAAE;QAChB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;QACzD,OAAO,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;QACxC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAA;YACrC,OAAO,OAAO,CAAA;QAChB,CAAC,CAAC,CAAA;QACF,MAAM,KAAK,GAAuB;YAChC,GAAG,IAAI;YACP,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;SACxF,CAAA;QACD,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QAClE,yIAAyI;IAC3I,CAAC,EAAE,SAAoB,CAAC,CAAA;IACxB,kGAAkG;IAClG,gBAAgB;IAChB,MAAM,KAAK,GAAG,GAAS,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC7C,KAAK,EAAE,CAAA;IACP,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,OAAO,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC5B,KAAK,EAAE,CAAA;IACT,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/ppr.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type HoleState } from "@nifrajs/web/internal/hole-runtime";
|
|
1
2
|
import { type JSX } from "solid-js";
|
|
2
3
|
/**
|
|
3
4
|
* The fields of a route's boundary declaration a hole renders from. `fallback` is a function: JSX
|
|
@@ -9,14 +10,6 @@ export interface HoleDefinition<Data> {
|
|
|
9
10
|
readonly fallback?: () => JSX.Element;
|
|
10
11
|
readonly interactive?: boolean;
|
|
11
12
|
}
|
|
12
|
-
/** The slice of a boundary state a hole reads: `ppr` marks a hole the shared shell left open, and
|
|
13
|
-
* `fill` that host's refill when the page reloads. */
|
|
14
|
-
interface HoleState {
|
|
15
|
-
readonly status: "unresolved" | "pending" | "ready" | "error";
|
|
16
|
-
readonly data?: unknown;
|
|
17
|
-
readonly ppr?: true;
|
|
18
|
-
readonly fill?: unknown;
|
|
19
|
-
}
|
|
20
13
|
export interface HoleProps<Data> {
|
|
21
14
|
readonly of: HoleDefinition<Data>;
|
|
22
15
|
readonly state: HoleState | undefined;
|
|
@@ -24,7 +17,7 @@ export interface HoleProps<Data> {
|
|
|
24
17
|
readonly error?: JSX.Element;
|
|
25
18
|
}
|
|
26
19
|
/**
|
|
27
|
-
*
|
|
20
|
+
* One `dynamic` or `shared` boundary of a partially prerendered page.
|
|
28
21
|
*
|
|
29
22
|
* In a shared shell the hole is an empty host Solid never fills: the PPR runtime puts the server's
|
|
30
23
|
* HTML into it, and an interactive hole then hydrates as its own root from the frame's props. When the
|
|
@@ -33,5 +26,4 @@ export interface HoleProps<Data> {
|
|
|
33
26
|
* navigation the hole renders like any streamed boundary.
|
|
34
27
|
*/
|
|
35
28
|
export declare function Hole<Data>(props: HoleProps<Data>): JSX.Element;
|
|
36
|
-
export {};
|
|
37
29
|
//# sourceMappingURL=ppr.d.ts.map
|
package/dist/ppr.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ppr.d.ts","sourceRoot":"","sources":["../src/ppr.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ppr.d.ts","sourceRoot":"","sources":["../src/ppr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,oCAAoC,CAAA;AAChF,OAAO,EAA+B,KAAK,GAAG,EAAW,MAAM,UAAU,CAAA;AAKzE;;;GAGG;AACH,MAAM,WAAW,cAAc,CAAC,IAAI;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,OAAO,CAAA;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,OAAO,CAAA;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,MAAM,WAAW,SAAS,CAAC,IAAI;IAC7B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAA;IACrC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;CAC7B;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,OAAO,CA4B9D"}
|
package/dist/ppr.js
CHANGED
|
@@ -18,7 +18,7 @@ function openHost(hole, fill) {
|
|
|
18
18
|
return clientHost(hole.name, hole.render, hole.interactive === true, attributes, fill);
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* One `dynamic` or `shared` boundary of a partially prerendered page.
|
|
22
22
|
*
|
|
23
23
|
* In a shared shell the hole is an empty host Solid never fills: the PPR runtime puts the server's
|
|
24
24
|
* HTML into it, and an interactive hole then hydrates as its own root from the frame's props. When the
|
package/dist/ppr.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ppr.js","sourceRoot":"","sources":["../src/ppr.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ppr.js","sourceRoot":"","sources":["../src/ppr.ts"],"names":[],"mappings":"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"}
|
package/dist/query.d.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import type { QueryClient, QueryOptions, QueryState } from "@nifrajs/web";
|
|
1
|
+
import type { DehydratedState, InfiniteData, InfiniteQueryOptions, MutationCallbacks, MutationContext, MutationState, QueryClient, QueryOptions, QueryState } from "@nifrajs/web";
|
|
2
2
|
/**
|
|
3
3
|
* `@nifrajs/web-solid/query` - Solid bindings for the keyed query-cache. `createQuery(key, fn)` bridges a
|
|
4
4
|
* query's `subscribe`/`snapshot` store into a Solid signal and fetches on mount; `useQueryClient`
|
|
5
5
|
* exposes `invalidateQueries` for after a mutation. Imports only `solid-js` + `@nifrajs/web` (never
|
|
6
6
|
* `solid-js/web`), so route components use it on the server *and* client. No JSX.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* accessor returns
|
|
8
|
+
* Without a provider, the query client is created lazily **client-side only** (`typeof window`) - on
|
|
9
|
+
* the server the accessor returns idle state and route loaders remain the data source. A
|
|
10
|
+
* `QueryClientProvider` can supply a request-scoped hydrated client.
|
|
10
11
|
* The `key` is captured once (Solid setup runs once); a reactive key is a documented future enhancement.
|
|
11
12
|
*/
|
|
12
|
-
import { type Accessor } from "solid-js";
|
|
13
|
+
import { type Accessor, type JSX } from "solid-js";
|
|
14
|
+
/** Provide a request-scoped client and optionally seed it before descendants run. */
|
|
15
|
+
export declare function QueryClientProvider(props: {
|
|
16
|
+
readonly client: QueryClient;
|
|
17
|
+
readonly state?: DehydratedState;
|
|
18
|
+
readonly children?: JSX.Element;
|
|
19
|
+
}): JSX.Element;
|
|
13
20
|
/** Access the query client to imperatively `invalidateQueries(keyOrPrefix)` (e.g. after a mutation). */
|
|
14
21
|
export declare function useQueryClient(): Pick<QueryClient, "invalidateQueries">;
|
|
15
22
|
/** A query's reactive state accessor plus `refetch`. */
|
|
@@ -26,4 +33,36 @@ export interface CreateQueryResult<T> {
|
|
|
26
33
|
* the live keys that refetch it.
|
|
27
34
|
*/
|
|
28
35
|
export declare function createQuery<T>(key: unknown, fn: () => Promise<T>, options?: QueryOptions): CreateQueryResult<T>;
|
|
36
|
+
/** A mutation result expressed as Solid accessors and imperative controls. */
|
|
37
|
+
export interface CreateMutationResult<TData, TVariables> {
|
|
38
|
+
readonly state: Accessor<MutationState<TData, TVariables>>;
|
|
39
|
+
readonly isIdle: Accessor<boolean>;
|
|
40
|
+
readonly isPending: Accessor<boolean>;
|
|
41
|
+
readonly isError: Accessor<boolean>;
|
|
42
|
+
readonly isSuccess: Accessor<boolean>;
|
|
43
|
+
readonly mutate: (variables: TVariables) => void;
|
|
44
|
+
readonly mutateAsync: (variables: TVariables) => Promise<TData>;
|
|
45
|
+
readonly reset: () => void;
|
|
46
|
+
readonly cancel: () => void;
|
|
47
|
+
}
|
|
48
|
+
/** Bind a mutation to a Solid owner. Identity changes discard late results and callbacks. */
|
|
49
|
+
export declare function createMutation<TData, TVariables = void>(fn: (variables: TVariables, context: MutationContext) => Promise<TData>, callbacks?: MutationCallbacks<TData, TVariables>): CreateMutationResult<TData, TVariables>;
|
|
50
|
+
/** Options for a Solid infinite query. */
|
|
51
|
+
export interface CreateInfiniteQueryOptions<T, P> extends InfiniteQueryOptions<T, P> {
|
|
52
|
+
readonly enabled?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** Infinite-query state and page controls expressed as Solid accessors. */
|
|
55
|
+
export interface CreateInfiniteQueryResult<T, P> {
|
|
56
|
+
readonly state: Accessor<QueryState<InfiniteData<T, P>>>;
|
|
57
|
+
readonly isPending: Accessor<boolean>;
|
|
58
|
+
readonly isError: Accessor<boolean>;
|
|
59
|
+
readonly isSuccess: Accessor<boolean>;
|
|
60
|
+
readonly hasNextPage: Accessor<boolean>;
|
|
61
|
+
readonly hasPreviousPage: Accessor<boolean>;
|
|
62
|
+
readonly fetchNextPage: () => Promise<InfiniteData<T, P>>;
|
|
63
|
+
readonly fetchPreviousPage: () => Promise<InfiniteData<T, P>>;
|
|
64
|
+
readonly refetch: () => Promise<InfiniteData<T, P>>;
|
|
65
|
+
}
|
|
66
|
+
/** Bind a paged query to a Solid owner and fetch its first page on mount. */
|
|
67
|
+
export declare function createInfiniteQuery<T, P>(key: unknown, fn: (pageParam: P) => Promise<T>, options: CreateInfiniteQueryOptions<T, P>): CreateInfiniteQueryResult<T, P>;
|
|
29
68
|
//# sourceMappingURL=query.d.ts.map
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/query.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createMutation as createMutationHandle } from "@nifrajs/web/client";
|
|
1
2
|
import { createNoClientRefetch, fetchOnMount, getQueryClientSingleton, IDLE_QUERY_STATE, noop, } from "@nifrajs/web/internal/query-runtime";
|
|
2
3
|
/**
|
|
3
4
|
* `@nifrajs/web-solid/query` - Solid bindings for the keyed query-cache. `createQuery(key, fn)` bridges a
|
|
@@ -5,14 +6,30 @@ import { createNoClientRefetch, fetchOnMount, getQueryClientSingleton, IDLE_QUER
|
|
|
5
6
|
* exposes `invalidateQueries` for after a mutation. Imports only `solid-js` + `@nifrajs/web` (never
|
|
6
7
|
* `solid-js/web`), so route components use it on the server *and* client. No JSX.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
* accessor returns
|
|
9
|
+
* Without a provider, the query client is created lazily **client-side only** (`typeof window`) - on
|
|
10
|
+
* the server the accessor returns idle state and route loaders remain the data source. A
|
|
11
|
+
* `QueryClientProvider` can supply a request-scoped hydrated client.
|
|
10
12
|
* The `key` is captured once (Solid setup runs once); a reactive key is a documented future enhancement.
|
|
11
13
|
*/
|
|
12
|
-
import { createSignal, onCleanup, onMount } from "solid-js";
|
|
14
|
+
import { createComponent, createContext, createSignal, onCleanup, onMount, useContext, } from "solid-js";
|
|
15
|
+
const QueryClientContext = createContext();
|
|
16
|
+
function queryClientForCurrentTree() {
|
|
17
|
+
return useContext(QueryClientContext) ?? getQueryClientSingleton();
|
|
18
|
+
}
|
|
19
|
+
/** Provide a request-scoped client and optionally seed it before descendants run. */
|
|
20
|
+
export function QueryClientProvider(props) {
|
|
21
|
+
if (props.state !== undefined)
|
|
22
|
+
props.client.hydrate(props.state);
|
|
23
|
+
return createComponent(QueryClientContext.Provider, {
|
|
24
|
+
value: props.client,
|
|
25
|
+
get children() {
|
|
26
|
+
return props.children;
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
13
30
|
/** Access the query client to imperatively `invalidateQueries(keyOrPrefix)` (e.g. after a mutation). */
|
|
14
31
|
export function useQueryClient() {
|
|
15
|
-
return
|
|
32
|
+
return queryClientForCurrentTree() ?? { invalidateQueries: noop };
|
|
16
33
|
}
|
|
17
34
|
/**
|
|
18
35
|
* Bind the keyed query for `key`, fetched via `fn`. Returns a reactive `state()` accessor + `refetch`.
|
|
@@ -21,7 +38,7 @@ export function useQueryClient() {
|
|
|
21
38
|
* the live keys that refetch it.
|
|
22
39
|
*/
|
|
23
40
|
export function createQuery(key, fn, options) {
|
|
24
|
-
const handle =
|
|
41
|
+
const handle = queryClientForCurrentTree()?.query(key, fn, options);
|
|
25
42
|
const [state, setState] = createSignal(handle ? handle.snapshot() : IDLE_QUERY_STATE);
|
|
26
43
|
if (handle !== undefined) {
|
|
27
44
|
onCleanup(handle.subscribe(() => setState(() => handle.snapshot())));
|
|
@@ -33,4 +50,55 @@ export function createQuery(key, fn, options) {
|
|
|
33
50
|
refetch: createNoClientRefetch("[nifra/web-solid]", "createQuery.refetch"),
|
|
34
51
|
};
|
|
35
52
|
}
|
|
53
|
+
/** Bind a mutation to a Solid owner. Identity changes discard late results and callbacks. */
|
|
54
|
+
export function createMutation(fn, callbacks = {}) {
|
|
55
|
+
const handle = createMutationHandle(fn, callbacks);
|
|
56
|
+
const [state, setState] = createSignal(handle.snapshot());
|
|
57
|
+
onCleanup(handle.subscribe(() => setState(() => handle.snapshot())));
|
|
58
|
+
return {
|
|
59
|
+
state,
|
|
60
|
+
isIdle: () => state().status === "idle",
|
|
61
|
+
isPending: () => state().status === "pending",
|
|
62
|
+
isError: () => state().status === "error",
|
|
63
|
+
isSuccess: () => state().status === "success",
|
|
64
|
+
mutate: (variables) => {
|
|
65
|
+
handle.mutate(variables).catch(noop);
|
|
66
|
+
},
|
|
67
|
+
mutateAsync: handle.mutate,
|
|
68
|
+
reset: handle.reset,
|
|
69
|
+
cancel: handle.cancel,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** Bind a paged query to a Solid owner and fetch its first page on mount. */
|
|
73
|
+
export function createInfiniteQuery(key, fn, options) {
|
|
74
|
+
const client = queryClientForCurrentTree();
|
|
75
|
+
const enabled = options.enabled !== false;
|
|
76
|
+
const handle = client?.infiniteQuery(key, fn, options);
|
|
77
|
+
const [state, setState] = createSignal(handle
|
|
78
|
+
? handle.snapshot()
|
|
79
|
+
: // biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: An idle query has no generic page data; the provider supplies the typed state before use.
|
|
80
|
+
IDLE_QUERY_STATE);
|
|
81
|
+
if (handle) {
|
|
82
|
+
onCleanup(handle.subscribe(() => setState(() => handle.snapshot())));
|
|
83
|
+
onMount(fetchOnMount(enabled ? handle : undefined));
|
|
84
|
+
}
|
|
85
|
+
const noClientAction = createNoClientRefetch("[nifra/web-solid]", "infinite query action");
|
|
86
|
+
return {
|
|
87
|
+
state,
|
|
88
|
+
isPending: () => state().status === "pending",
|
|
89
|
+
isError: () => state().status === "error",
|
|
90
|
+
isSuccess: () => state().status === "success",
|
|
91
|
+
hasNextPage: () => {
|
|
92
|
+
state();
|
|
93
|
+
return handle?.hasNextPage() ?? false;
|
|
94
|
+
},
|
|
95
|
+
hasPreviousPage: () => {
|
|
96
|
+
state();
|
|
97
|
+
return handle?.hasPreviousPage() ?? false;
|
|
98
|
+
},
|
|
99
|
+
fetchNextPage: handle?.fetchNextPage ?? noClientAction,
|
|
100
|
+
fetchPreviousPage: handle?.fetchPreviousPage ?? noClientAction,
|
|
101
|
+
refetch: handle?.refetch ?? noClientAction,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
36
104
|
//# sourceMappingURL=query.js.map
|
package/dist/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/router.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { Blocker, BlockerFunction, BlockerState, NavigateFunction, RenderPr
|
|
|
8
8
|
* reads the accessor `compose` provides on SSR + client mount alike. Imports only `solid-js`. No JSX.
|
|
9
9
|
*/
|
|
10
10
|
import { type Accessor, type Context } from "solid-js";
|
|
11
|
+
export { href, rawHref } from "@nifrajs/web/client";
|
|
11
12
|
export { onPageHide, onPageShow, usePageVisibility } from "./page-visibility.js";
|
|
12
13
|
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction, UIMatch };
|
|
13
14
|
export declare const SearchContext: Context<Accessor<Record<string, unknown>> | undefined>;
|
|
@@ -38,7 +39,7 @@ export declare function useMatches(): Accessor<readonly UIMatch[]>;
|
|
|
38
39
|
* ```
|
|
39
40
|
*/
|
|
40
41
|
export declare function useSearch<Schema extends StandardSchemaV1 | undefined = undefined>(): Accessor<Schema extends StandardSchemaV1 ? InferOutput<Schema> : Record<string, unknown>>;
|
|
41
|
-
/** Get the {@link NavigateFunction} (
|
|
42
|
+
/** Get the {@link NavigateFunction} (an `Href` from `href()` or `rawHref()`, or a history delta).
|
|
42
43
|
* Resolves the browser navigate at call time, so it works as soon as `installHistory` has run and no-ops
|
|
43
44
|
* before then / on the server. */
|
|
44
45
|
export declare function useNavigate(): NavigateFunction;
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAIzE,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAIzE,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,OAAO,EACR,MAAM,cAAc,CAAA;AAOrB;;;;;;GAMG;AACH,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EAMb,MAAM,UAAU,CAAA;AAGjB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAChF,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAA;AAiBjF,eAAO,MAAM,aAAa,wDACoE,CAAA;AAO9F,eAAO,MAAM,kBAAkB,kCACuC,CAAA;AAKtE;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,IAAI,QAAQ,CAAC,SAAS,OAAO,EAAE,CAAC,CAIzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,MAAM,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,KAAK,QAAQ,CAC5F,MAAM,SAAS,gBAAgB,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAChF,CAIA;AAED;;kCAEkC;AAClC,wBAAgB,WAAW,IAAI,gBAAgB,CAE9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,OAAO,GAAG,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,CAYpF"}
|
package/dist/router.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// `/client`, not the root - these are DOM values, and the root's graph carries the
|
|
2
2
|
// server, which Vite's dev server evaluates rather than tree-shakes.
|
|
3
|
-
import {
|
|
3
|
+
import { IDLE_BLOCKER, registerBlocker } from "@nifrajs/web/client";
|
|
4
4
|
// Its own subpath, so an app that never calls `useMatches` never bundles it.
|
|
5
5
|
import { chainMatches } from "@nifrajs/web/internal/matches-runtime";
|
|
6
|
+
import { navigateNow } from "@nifrajs/web/internal/navigate-runtime";
|
|
6
7
|
/**
|
|
7
8
|
* `@nifrajs/web-solid/router` - Solid routing bindings over the agnostic `@nifrajs/web` history layer:
|
|
8
9
|
* `useNavigate` (programmatic navigation), `useBlocker` (the unsaved-changes guard), and `useSearch`
|
|
@@ -12,6 +13,7 @@ import { chainMatches } from "@nifrajs/web/internal/matches-runtime";
|
|
|
12
13
|
*/
|
|
13
14
|
import { createContext, createMemo, createSignal, onCleanup, useContext, } from "solid-js";
|
|
14
15
|
import { PageContext } from "./page-visibility.js";
|
|
16
|
+
export { href, rawHref } from "@nifrajs/web/client";
|
|
15
17
|
export { onPageHide, onPageShow, usePageVisibility } from "./page-visibility.js";
|
|
16
18
|
// Frozen empty search + a stable accessor for a `useSearch` used outside a nifra route tree.
|
|
17
19
|
const EMPTY_SEARCH = Object.freeze({});
|
|
@@ -67,17 +69,11 @@ export function useMatches() {
|
|
|
67
69
|
export function useSearch() {
|
|
68
70
|
return (useContext(SearchContext) ?? EMPTY_SEARCH_ACCESSOR);
|
|
69
71
|
}
|
|
70
|
-
/** Get the {@link NavigateFunction} (
|
|
72
|
+
/** Get the {@link NavigateFunction} (an `Href` from `href()` or `rawHref()`, or a history delta).
|
|
71
73
|
* Resolves the browser navigate at call time, so it works as soon as `installHistory` has run and no-ops
|
|
72
74
|
* before then / on the server. */
|
|
73
75
|
export function useNavigate() {
|
|
74
|
-
return
|
|
75
|
-
const navigate = getBrowserNavigate();
|
|
76
|
-
if (navigate === undefined)
|
|
77
|
-
return;
|
|
78
|
-
const resolved = resolveNavigate(to, options);
|
|
79
|
-
navigate(resolved.to, resolved.options);
|
|
80
|
-
});
|
|
76
|
+
return navigateNow;
|
|
81
77
|
}
|
|
82
78
|
/**
|
|
83
79
|
* Guard navigation away from a page with unsaved work, confirming with your OWN async UI. Mirrors
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAYA,mFAAmF;AACnF,qEAAqE;AACrE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACnE,6EAA6E;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAA;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AACpE;;;;;;GAMG;AACH,OAAO,EAGL,aAAa,EACb,UAAU,EACV,YAAY,EACZ,SAAS,EACT,UAAU,GACX,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAGhF,6FAA6F;AAC7F,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AACzE,MAAM,qBAAqB,GAAsC,GAAG,EAAE,CAAC,YAAY,CAAA;AAEnF;;;;;;2BAM2B;AAC3B,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;AACxE,MAAM,iBAAiB,GAAG,UAEzB,CAAA;AACD,MAAM,CAAC,MAAM,aAAa,GACxB,iBAAiB,CAAC,mBAAmB,CAAC,IAAI,aAAa,EAAqC,CAAA;AAC9F,iBAAiB,CAAC,mBAAmB,CAAC,GAAG,aAAa,CAAA;AAEtD;sGACsG;AACtG,MAAM,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;AACtE,MAAM,gBAAgB,GAAG,UAAyE,CAAA;AAClG,MAAM,CAAC,MAAM,kBAAkB,GAC7B,gBAAgB,CAAC,kBAAkB,CAAC,IAAI,aAAa,EAAe,CAAA;AACtE,gBAAgB,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,CAAA;AAEzD,MAAM,UAAU,GAAuB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAExD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,KAAK,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAA;IAC5C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,EAAE,CAAC,UAAU,CAAA;IAChD,OAAO,UAAU,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;AAC9C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS;IAGvB,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAEzD,CAAA;AACH,CAAC;AAED;;kCAEkC;AAClC,MAAM,UAAU,WAAW;IACzB,OAAO,WAAW,CAAA;AACpB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAC,WAAsC;IAC/D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAU,YAAY,CAAC,CAAA;IACjE,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IACpC,SAAS,CACP,eAAe,CACb,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI;QACvB,CAAC,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EACvE,UAAU,CACX,CACF,CAAA;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nifrajs/web-solid",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"description": "Solid render adapter for @nifrajs/web - SSR + hydration, with the Solid Babel build plugin (@nifrajs/web-solid/plugin).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -132,16 +132,16 @@
|
|
|
132
132
|
"dependencies": {
|
|
133
133
|
"@babel/core": "^7.26.0",
|
|
134
134
|
"@babel/preset-typescript": "^7.26.0",
|
|
135
|
-
"@nifrajs/core": "5.
|
|
136
|
-
"@nifrajs/web": "5.
|
|
135
|
+
"@nifrajs/core": "5.10.0",
|
|
136
|
+
"@nifrajs/web": "5.10.0",
|
|
137
137
|
"babel-preset-solid": "^1.9.3",
|
|
138
138
|
"solid-refresh": "^0.7.8"
|
|
139
139
|
},
|
|
140
140
|
"peerDependencies": {
|
|
141
141
|
"@mdx-js/mdx": "^3",
|
|
142
142
|
"solid-js": "^1.9.0",
|
|
143
|
-
"@nifrajs/i18n": "^5.
|
|
144
|
-
"@nifrajs/image": "^5.
|
|
143
|
+
"@nifrajs/i18n": "^5.10.0",
|
|
144
|
+
"@nifrajs/image": "^5.10.0"
|
|
145
145
|
},
|
|
146
146
|
"peerDependenciesMeta": {
|
|
147
147
|
"@mdx-js/mdx": {
|
package/src/compose.ts
CHANGED
|
@@ -29,7 +29,9 @@ export function compose(chain: readonly unknown[], props: RenderProps): () => JS
|
|
|
29
29
|
get data() {
|
|
30
30
|
return props.layoutData?.[i] ?? null
|
|
31
31
|
},
|
|
32
|
-
|
|
32
|
+
get boundaries() {
|
|
33
|
+
return props.boundaries
|
|
34
|
+
},
|
|
33
35
|
children: child(),
|
|
34
36
|
})
|
|
35
37
|
}
|
package/src/fn.ts
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* "is it pending" has one answer rather than five that drift. This file contributes only a signal fed by the store.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type { ServerFnReference } from "@nifrajs/web/fn"
|
|
12
12
|
import { createServerFnStore, type ServerFnState } from "@nifrajs/web/fn-state"
|
|
13
|
+
import { clientServerFn } from "@nifrajs/web/internal/client-server-fn"
|
|
13
14
|
import { type Accessor, createSignal, onCleanup } from "solid-js"
|
|
14
15
|
|
|
15
16
|
/** A server function's state accessor plus the call itself. */
|
|
@@ -31,7 +32,7 @@ export interface ServerFnHandle<Input, Output> {
|
|
|
31
32
|
export function useServerFn<Input, Output>(
|
|
32
33
|
fn: ServerFnReference<Input, Output>,
|
|
33
34
|
): ServerFnHandle<Input, Output> {
|
|
34
|
-
const store = createServerFnStore(fn
|
|
35
|
+
const store = createServerFnStore(clientServerFn(fn))
|
|
35
36
|
// Seeded from the store, not from the idle constant. They are the same value here - the store is
|
|
36
37
|
// created one line up and cannot have moved - so this is correctness that does not depend on that
|
|
37
38
|
// staying true. Svelte had exactly this line reading the constant, and when its subscription turned
|
package/src/image.ts
CHANGED
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
* reactively (`splitProps`/`mergeProps`). Resizing is delegated to the `loader`; nifra bundles no codec.
|
|
7
7
|
* No JSX (`createComponent`/`Dynamic`), so the package builds with plain `tsc`.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
type ImageInputProps,
|
|
11
|
+
type ImageLoader,
|
|
12
|
+
type ImageProps,
|
|
13
|
+
resolveImage,
|
|
14
|
+
type StaticImageProps,
|
|
15
|
+
toHtmlAttrs,
|
|
16
|
+
} from "@nifrajs/image"
|
|
10
17
|
import { createComponent, type JSX, mergeProps, splitProps } from "solid-js"
|
|
11
18
|
import { Dynamic } from "solid-js/web"
|
|
12
19
|
|
|
@@ -29,11 +36,14 @@ export interface ImageComponentProps
|
|
|
29
36
|
readonly loader?: ImageLoader
|
|
30
37
|
}
|
|
31
38
|
|
|
39
|
+
export type StaticImageComponentProps = StaticImageProps &
|
|
40
|
+
Omit<ImageComponentProps, "src" | "width" | "height">
|
|
41
|
+
|
|
32
42
|
/**
|
|
33
|
-
* Render a responsive, CLS-safe `<img>`.
|
|
43
|
+
* Render a responsive, CLS-safe `<img>`. String URLs require dimensions; asset imports infer them;
|
|
34
44
|
* `priority` marks the LCP image (`eager` + `fetchpriority="high"`). Extra DOM props pass through.
|
|
35
45
|
*/
|
|
36
|
-
export function Image(props: ImageComponentProps): JSX.Element {
|
|
46
|
+
export function Image(props: ImageComponentProps | StaticImageComponentProps): JSX.Element {
|
|
37
47
|
// Separate the nifra-only props (not valid DOM attributes) from the DOM passthrough (`rest`), keeping
|
|
38
48
|
// both reactive. `rest` carries class/style/id/handlers; the computed attrs are layered over it.
|
|
39
49
|
const [, rest] = splitProps(props, [
|
|
@@ -51,10 +61,7 @@ export function Image(props: ImageComponentProps): JSX.Element {
|
|
|
51
61
|
const attrs = (): ReturnType<typeof toHtmlAttrs> => {
|
|
52
62
|
// Build ImageProps via conditional spreads (exactOptionalPropertyTypes: an unset optional is
|
|
53
63
|
// absent, not `undefined`). resolveImage validates width/height > 0 (CLS contract).
|
|
54
|
-
const
|
|
55
|
-
src: props.src,
|
|
56
|
-
width: props.width,
|
|
57
|
-
height: props.height,
|
|
64
|
+
const common = {
|
|
58
65
|
alt: props.alt,
|
|
59
66
|
...(props.sizes !== undefined ? { sizes: props.sizes } : {}),
|
|
60
67
|
...(props.widths !== undefined ? { widths: props.widths } : {}),
|
|
@@ -62,6 +69,20 @@ export function Image(props: ImageComponentProps): JSX.Element {
|
|
|
62
69
|
...(props.loading !== undefined ? { loading: props.loading } : {}),
|
|
63
70
|
...(props.priority !== undefined ? { priority: props.priority } : {}),
|
|
64
71
|
}
|
|
72
|
+
const input: ImageInputProps =
|
|
73
|
+
typeof props.src === "string"
|
|
74
|
+
? {
|
|
75
|
+
...common,
|
|
76
|
+
src: props.src,
|
|
77
|
+
width: props.width ?? Number.NaN,
|
|
78
|
+
height: props.height ?? Number.NaN,
|
|
79
|
+
}
|
|
80
|
+
: {
|
|
81
|
+
...common,
|
|
82
|
+
src: props.src,
|
|
83
|
+
...(props.width !== undefined ? { width: props.width } : {}),
|
|
84
|
+
...(props.height !== undefined ? { height: props.height } : {}),
|
|
85
|
+
}
|
|
65
86
|
return toHtmlAttrs(resolveImage(input, props.loader))
|
|
66
87
|
}
|
|
67
88
|
return createComponent(Dynamic, mergeProps(rest, attrs, { component: "img" }))
|
package/src/keep-alive.ts
CHANGED
|
@@ -9,13 +9,8 @@
|
|
|
9
9
|
* in place, synchronously, so the DOM half runs right after each publish.
|
|
10
10
|
*/
|
|
11
11
|
import type { MountRouterOptions, RouterState } from "@nifrajs/web"
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
type KeepAliveRouter,
|
|
15
|
-
type KeepAliveTable,
|
|
16
|
-
type SlotNode,
|
|
17
|
-
slotTree,
|
|
18
|
-
} from "@nifrajs/web/keep-alive"
|
|
12
|
+
import { keptMount } from "@nifrajs/web/internal/keep-alive-mount"
|
|
13
|
+
import type { KeepAliveRouter, KeepAliveTable, SlotNode } from "@nifrajs/web/keep-alive"
|
|
19
14
|
import { createMemo, createSignal } from "solid-js"
|
|
20
15
|
import { hydrate as solidHydrate } from "solid-js/web"
|
|
21
16
|
import { setMountedRouter } from "./fetcher.ts"
|
|
@@ -36,38 +31,30 @@ export interface KeepAliveMountOptions extends MountRouterOptions {
|
|
|
36
31
|
* wrappers the server rendered), so hydration claims the document as it is.
|
|
37
32
|
*/
|
|
38
33
|
export function mountRouter(options: KeepAliveMountOptions): void {
|
|
39
|
-
const { router,
|
|
34
|
+
const { router, searchSchemas, container } = options
|
|
40
35
|
const matchChains = options.matchChains ?? {}
|
|
41
36
|
setMountedRouter(router)
|
|
42
|
-
const
|
|
43
|
-
let committed: readonly SlotNode[] | undefined
|
|
44
|
-
router.beforePublish((next) => parking.before(slotTree(next, matchChains, table, committed)))
|
|
37
|
+
const kept = keptMount(options)
|
|
45
38
|
|
|
46
39
|
let current: readonly SlotNode[] = []
|
|
47
40
|
let publish: ((state: RouterState) => void) | undefined
|
|
48
|
-
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: the generated entry passes the element the server rendered the app into
|
|
49
41
|
solidHydrate(() => {
|
|
50
42
|
const [state, setState] = createSignal(router.snapshot())
|
|
51
43
|
publish = (next) => setState(() => next)
|
|
52
44
|
const tree = createMemo(() => {
|
|
53
|
-
current =
|
|
45
|
+
current = kept.tree(state(), current)
|
|
54
46
|
return current
|
|
55
47
|
})
|
|
56
48
|
const mount: KeepAliveViewMount = {
|
|
49
|
+
...kept,
|
|
57
50
|
propsOf: (of) => routeProps(of, searchSchemas, matchChains, (read) => createMemo(read)),
|
|
58
|
-
chainOf: (of) => routes[of.routeId] ?? [],
|
|
59
|
-
entry: parking.entry,
|
|
60
|
-
page: parking.page,
|
|
61
51
|
}
|
|
62
52
|
return KeepAliveView({ tree, shown: mount.propsOf(state), mount })
|
|
63
53
|
// biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: the generated entry passes the element the server rendered the app into
|
|
64
54
|
}, container as Element)
|
|
65
55
|
// Solid has updated the document by the time a publish returns: park what it hid, restore what it
|
|
66
56
|
// showed again.
|
|
67
|
-
const after = (): void =>
|
|
68
|
-
committed = current
|
|
69
|
-
parking.after(current)
|
|
70
|
-
}
|
|
57
|
+
const after = (): void => kept.after(current)
|
|
71
58
|
after()
|
|
72
59
|
router.subscribe(() => {
|
|
73
60
|
publish?.(router.snapshot())
|
package/src/ppr.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { initialHtml } from "@nifrajs/web/internal/hole-runtime"
|
|
1
|
+
import { type HoleState, initialHtml } from "@nifrajs/web/internal/hole-runtime"
|
|
2
2
|
import { createComponent, createMemo, type JSX, untrack } from "solid-js"
|
|
3
3
|
import { Dynamic, isServer } from "solid-js/web"
|
|
4
4
|
import { Await } from "./await.ts"
|
|
@@ -15,15 +15,6 @@ export interface HoleDefinition<Data> {
|
|
|
15
15
|
readonly interactive?: boolean
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/** The slice of a boundary state a hole reads: `ppr` marks a hole the shared shell left open, and
|
|
19
|
-
* `fill` that host's refill when the page reloads. */
|
|
20
|
-
interface HoleState {
|
|
21
|
-
readonly status: "unresolved" | "pending" | "ready" | "error"
|
|
22
|
-
readonly data?: unknown
|
|
23
|
-
readonly ppr?: true
|
|
24
|
-
readonly fill?: unknown
|
|
25
|
-
}
|
|
26
|
-
|
|
27
18
|
export interface HoleProps<Data> {
|
|
28
19
|
readonly of: HoleDefinition<Data>
|
|
29
20
|
readonly state: HoleState | undefined
|
|
@@ -47,7 +38,7 @@ function openHost<Data>(hole: HoleDefinition<Data>, fill: () => unknown): JSX.El
|
|
|
47
38
|
}
|
|
48
39
|
|
|
49
40
|
/**
|
|
50
|
-
*
|
|
41
|
+
* One `dynamic` or `shared` boundary of a partially prerendered page.
|
|
51
42
|
*
|
|
52
43
|
* In a shared shell the hole is an empty host Solid never fills: the PPR runtime puts the server's
|
|
53
44
|
* HTML into it, and an interactive hole then hydrates as its own root from the frame's props. When the
|
package/src/query.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
DehydratedState,
|
|
3
|
+
InfiniteData,
|
|
4
|
+
InfiniteQueryOptions,
|
|
5
|
+
MutationCallbacks,
|
|
6
|
+
MutationContext,
|
|
7
|
+
MutationHandle,
|
|
8
|
+
MutationState,
|
|
9
|
+
QueryClient,
|
|
10
|
+
QueryOptions,
|
|
11
|
+
QueryState,
|
|
12
|
+
} from "@nifrajs/web"
|
|
13
|
+
import { createMutation as createMutationHandle } from "@nifrajs/web/client"
|
|
2
14
|
import {
|
|
3
15
|
createNoClientRefetch,
|
|
4
16
|
fetchOnMount,
|
|
@@ -12,15 +24,46 @@ import {
|
|
|
12
24
|
* exposes `invalidateQueries` for after a mutation. Imports only `solid-js` + `@nifrajs/web` (never
|
|
13
25
|
* `solid-js/web`), so route components use it on the server *and* client. No JSX.
|
|
14
26
|
*
|
|
15
|
-
*
|
|
16
|
-
* accessor returns
|
|
27
|
+
* Without a provider, the query client is created lazily **client-side only** (`typeof window`) - on
|
|
28
|
+
* the server the accessor returns idle state and route loaders remain the data source. A
|
|
29
|
+
* `QueryClientProvider` can supply a request-scoped hydrated client.
|
|
17
30
|
* The `key` is captured once (Solid setup runs once); a reactive key is a documented future enhancement.
|
|
18
31
|
*/
|
|
19
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
type Accessor,
|
|
34
|
+
createComponent,
|
|
35
|
+
createContext,
|
|
36
|
+
createSignal,
|
|
37
|
+
type JSX,
|
|
38
|
+
onCleanup,
|
|
39
|
+
onMount,
|
|
40
|
+
useContext,
|
|
41
|
+
} from "solid-js"
|
|
42
|
+
|
|
43
|
+
const QueryClientContext = createContext<QueryClient>()
|
|
44
|
+
|
|
45
|
+
function queryClientForCurrentTree(): QueryClient | undefined {
|
|
46
|
+
return useContext(QueryClientContext) ?? getQueryClientSingleton()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Provide a request-scoped client and optionally seed it before descendants run. */
|
|
50
|
+
export function QueryClientProvider(props: {
|
|
51
|
+
readonly client: QueryClient
|
|
52
|
+
readonly state?: DehydratedState
|
|
53
|
+
readonly children?: JSX.Element
|
|
54
|
+
}): JSX.Element {
|
|
55
|
+
if (props.state !== undefined) props.client.hydrate(props.state)
|
|
56
|
+
return createComponent(QueryClientContext.Provider, {
|
|
57
|
+
value: props.client,
|
|
58
|
+
get children() {
|
|
59
|
+
return props.children
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
}
|
|
20
63
|
|
|
21
64
|
/** Access the query client to imperatively `invalidateQueries(keyOrPrefix)` (e.g. after a mutation). */
|
|
22
65
|
export function useQueryClient(): Pick<QueryClient, "invalidateQueries"> {
|
|
23
|
-
return
|
|
66
|
+
return queryClientForCurrentTree() ?? { invalidateQueries: noop }
|
|
24
67
|
}
|
|
25
68
|
|
|
26
69
|
/** A query's reactive state accessor plus `refetch`. */
|
|
@@ -42,7 +85,7 @@ export function createQuery<T>(
|
|
|
42
85
|
fn: () => Promise<T>,
|
|
43
86
|
options?: QueryOptions,
|
|
44
87
|
): CreateQueryResult<T> {
|
|
45
|
-
const handle =
|
|
88
|
+
const handle = queryClientForCurrentTree()?.query<T>(key, fn, options)
|
|
46
89
|
const [state, setState] = createSignal<QueryState<T>>(
|
|
47
90
|
handle ? handle.snapshot() : IDLE_QUERY_STATE,
|
|
48
91
|
)
|
|
@@ -56,3 +99,99 @@ export function createQuery<T>(
|
|
|
56
99
|
refetch: createNoClientRefetch<T>("[nifra/web-solid]", "createQuery.refetch"),
|
|
57
100
|
}
|
|
58
101
|
}
|
|
102
|
+
|
|
103
|
+
/** A mutation result expressed as Solid accessors and imperative controls. */
|
|
104
|
+
export interface CreateMutationResult<TData, TVariables> {
|
|
105
|
+
readonly state: Accessor<MutationState<TData, TVariables>>
|
|
106
|
+
readonly isIdle: Accessor<boolean>
|
|
107
|
+
readonly isPending: Accessor<boolean>
|
|
108
|
+
readonly isError: Accessor<boolean>
|
|
109
|
+
readonly isSuccess: Accessor<boolean>
|
|
110
|
+
readonly mutate: (variables: TVariables) => void
|
|
111
|
+
readonly mutateAsync: (variables: TVariables) => Promise<TData>
|
|
112
|
+
readonly reset: () => void
|
|
113
|
+
readonly cancel: () => void
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Bind a mutation to a Solid owner. Identity changes discard late results and callbacks. */
|
|
117
|
+
export function createMutation<TData, TVariables = void>(
|
|
118
|
+
fn: (variables: TVariables, context: MutationContext) => Promise<TData>,
|
|
119
|
+
callbacks: MutationCallbacks<TData, TVariables> = {},
|
|
120
|
+
): CreateMutationResult<TData, TVariables> {
|
|
121
|
+
const handle: MutationHandle<TData, TVariables> = createMutationHandle(fn, callbacks)
|
|
122
|
+
const [state, setState] = createSignal(handle.snapshot())
|
|
123
|
+
onCleanup(handle.subscribe(() => setState(() => handle.snapshot())))
|
|
124
|
+
return {
|
|
125
|
+
state,
|
|
126
|
+
isIdle: () => state().status === "idle",
|
|
127
|
+
isPending: () => state().status === "pending",
|
|
128
|
+
isError: () => state().status === "error",
|
|
129
|
+
isSuccess: () => state().status === "success",
|
|
130
|
+
mutate: (variables) => {
|
|
131
|
+
handle.mutate(variables).catch(noop)
|
|
132
|
+
},
|
|
133
|
+
mutateAsync: handle.mutate,
|
|
134
|
+
reset: handle.reset,
|
|
135
|
+
cancel: handle.cancel,
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Options for a Solid infinite query. */
|
|
140
|
+
export interface CreateInfiniteQueryOptions<T, P> extends InfiniteQueryOptions<T, P> {
|
|
141
|
+
readonly enabled?: boolean
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Infinite-query state and page controls expressed as Solid accessors. */
|
|
145
|
+
export interface CreateInfiniteQueryResult<T, P> {
|
|
146
|
+
readonly state: Accessor<QueryState<InfiniteData<T, P>>>
|
|
147
|
+
readonly isPending: Accessor<boolean>
|
|
148
|
+
readonly isError: Accessor<boolean>
|
|
149
|
+
readonly isSuccess: Accessor<boolean>
|
|
150
|
+
readonly hasNextPage: Accessor<boolean>
|
|
151
|
+
readonly hasPreviousPage: Accessor<boolean>
|
|
152
|
+
readonly fetchNextPage: () => Promise<InfiniteData<T, P>>
|
|
153
|
+
readonly fetchPreviousPage: () => Promise<InfiniteData<T, P>>
|
|
154
|
+
readonly refetch: () => Promise<InfiniteData<T, P>>
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Bind a paged query to a Solid owner and fetch its first page on mount. */
|
|
158
|
+
export function createInfiniteQuery<T, P>(
|
|
159
|
+
key: unknown,
|
|
160
|
+
fn: (pageParam: P) => Promise<T>,
|
|
161
|
+
options: CreateInfiniteQueryOptions<T, P>,
|
|
162
|
+
): CreateInfiniteQueryResult<T, P> {
|
|
163
|
+
const client = queryClientForCurrentTree()
|
|
164
|
+
const enabled = options.enabled !== false
|
|
165
|
+
const handle = client?.infiniteQuery<T, P>(key, fn, options)
|
|
166
|
+
const [state, setState] = createSignal<QueryState<InfiniteData<T, P>>>(
|
|
167
|
+
handle
|
|
168
|
+
? handle.snapshot()
|
|
169
|
+
: // biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: An idle query has no generic page data; the provider supplies the typed state before use.
|
|
170
|
+
(IDLE_QUERY_STATE as QueryState<InfiniteData<T, P>>),
|
|
171
|
+
)
|
|
172
|
+
if (handle) {
|
|
173
|
+
onCleanup(handle.subscribe(() => setState(() => handle.snapshot())))
|
|
174
|
+
onMount(fetchOnMount(enabled ? handle : undefined))
|
|
175
|
+
}
|
|
176
|
+
const noClientAction = createNoClientRefetch<InfiniteData<T, P>>(
|
|
177
|
+
"[nifra/web-solid]",
|
|
178
|
+
"infinite query action",
|
|
179
|
+
)
|
|
180
|
+
return {
|
|
181
|
+
state,
|
|
182
|
+
isPending: () => state().status === "pending",
|
|
183
|
+
isError: () => state().status === "error",
|
|
184
|
+
isSuccess: () => state().status === "success",
|
|
185
|
+
hasNextPage: () => {
|
|
186
|
+
state()
|
|
187
|
+
return handle?.hasNextPage() ?? false
|
|
188
|
+
},
|
|
189
|
+
hasPreviousPage: () => {
|
|
190
|
+
state()
|
|
191
|
+
return handle?.hasPreviousPage() ?? false
|
|
192
|
+
},
|
|
193
|
+
fetchNextPage: handle?.fetchNextPage ?? noClientAction,
|
|
194
|
+
fetchPreviousPage: handle?.fetchPreviousPage ?? noClientAction,
|
|
195
|
+
refetch: handle?.refetch ?? noClientAction,
|
|
196
|
+
}
|
|
197
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
1
|
import type { InferOutput, StandardSchemaV1 } from "@nifrajs/core/server"
|
|
2
2
|
// `import type` + a local re-export, NOT `export type { … } from "@nifrajs/web"`: that form leaves a
|
|
3
3
|
// bare `import "@nifrajs/web"` in the output, which pulls the server graph into the browser under
|
|
4
|
-
// Vite's dev server. Sourced from the ROOT so the generated `
|
|
4
|
+
// Vite's dev server. Sourced from the ROOT so the generated `RouteTable` augmentation applies.
|
|
5
5
|
import type {
|
|
6
6
|
Blocker,
|
|
7
7
|
BlockerFunction,
|
|
8
8
|
BlockerState,
|
|
9
9
|
NavigateFunction,
|
|
10
|
-
NavigateOptions,
|
|
11
|
-
NavigateTargetInput,
|
|
12
10
|
RenderProps,
|
|
13
11
|
UIMatch,
|
|
14
12
|
} from "@nifrajs/web"
|
|
15
13
|
// `/client`, not the root - these are DOM values, and the root's graph carries the
|
|
16
14
|
// server, which Vite's dev server evaluates rather than tree-shakes.
|
|
17
|
-
import {
|
|
18
|
-
getBrowserNavigate,
|
|
19
|
-
IDLE_BLOCKER,
|
|
20
|
-
registerBlocker,
|
|
21
|
-
resolveNavigate,
|
|
22
|
-
} from "@nifrajs/web/client"
|
|
15
|
+
import { IDLE_BLOCKER, registerBlocker } from "@nifrajs/web/client"
|
|
23
16
|
// Its own subpath, so an app that never calls `useMatches` never bundles it.
|
|
24
17
|
import { chainMatches } from "@nifrajs/web/internal/matches-runtime"
|
|
18
|
+
import { navigateNow } from "@nifrajs/web/internal/navigate-runtime"
|
|
25
19
|
/**
|
|
26
20
|
* `@nifrajs/web-solid/router` - Solid routing bindings over the agnostic `@nifrajs/web` history layer:
|
|
27
21
|
* `useNavigate` (programmatic navigation), `useBlocker` (the unsaved-changes guard), and `useSearch`
|
|
@@ -40,6 +34,7 @@ import {
|
|
|
40
34
|
} from "solid-js"
|
|
41
35
|
import { PageContext } from "./page-visibility.ts"
|
|
42
36
|
|
|
37
|
+
export { href, rawHref } from "@nifrajs/web/client"
|
|
43
38
|
export { onPageHide, onPageShow, usePageVisibility } from "./page-visibility.ts"
|
|
44
39
|
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction, UIMatch }
|
|
45
40
|
|
|
@@ -110,16 +105,11 @@ export function useSearch<Schema extends StandardSchemaV1 | undefined = undefine
|
|
|
110
105
|
>
|
|
111
106
|
}
|
|
112
107
|
|
|
113
|
-
/** Get the {@link NavigateFunction} (
|
|
108
|
+
/** Get the {@link NavigateFunction} (an `Href` from `href()` or `rawHref()`, or a history delta).
|
|
114
109
|
* Resolves the browser navigate at call time, so it works as soon as `installHistory` has run and no-ops
|
|
115
110
|
* before then / on the server. */
|
|
116
111
|
export function useNavigate(): NavigateFunction {
|
|
117
|
-
return
|
|
118
|
-
const navigate = getBrowserNavigate()
|
|
119
|
-
if (navigate === undefined) return
|
|
120
|
-
const resolved = resolveNavigate(to, options)
|
|
121
|
-
navigate(resolved.to, resolved.options)
|
|
122
|
-
}) as NavigateFunction
|
|
112
|
+
return navigateNow
|
|
123
113
|
}
|
|
124
114
|
|
|
125
115
|
/**
|