@solidjs/router 0.14.1 → 0.14.3
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/README.md +9 -1
- package/dist/data/createAsync.d.ts +12 -7
- package/dist/data/createAsync.js +16 -4
- package/dist/data/index.d.ts +1 -1
- package/dist/index.js +32 -11
- package/dist/routers/Router.js +1 -1
- package/dist/routers/StaticRouter.js +1 -2
- package/dist/routers/createRouter.js +3 -1
- package/dist/routing.js +7 -3
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -495,11 +495,19 @@ This is light wrapper over `createResource` that aims to serve as stand-in for a
|
|
|
495
495
|
const user = createAsync((currentValue) => getUser(params.id))
|
|
496
496
|
```
|
|
497
497
|
|
|
498
|
+
It also preserves `latest` field from `createResource`. Note that it will be removed in the future.
|
|
499
|
+
|
|
500
|
+
```jsx
|
|
501
|
+
const user = createAsync((currentValue) => getUser(params.id))
|
|
502
|
+
return <h1>{user.latest.name}</h1>;
|
|
503
|
+
```
|
|
504
|
+
|
|
498
505
|
Using `cache` in `createResource` directly won't work properly as the fetcher is not reactive and it won't invalidate properly.
|
|
499
506
|
|
|
500
507
|
### `createAsyncStore`
|
|
501
508
|
|
|
502
509
|
Similar to `createAsync` except it uses a deeply reactive store. Perfect for applying fine-grained changes to large model data that updates.
|
|
510
|
+
It also supports `latest` field which will be removed in the future.
|
|
503
511
|
|
|
504
512
|
```jsx
|
|
505
513
|
const todos = createAsyncStore(() => getTodos());
|
|
@@ -727,7 +735,7 @@ This is the main Router component for the browser.
|
|
|
727
735
|
| base | string | Base url to use for matching routes |
|
|
728
736
|
| actionBase | string | Root url for server actions, default: `/_server` |
|
|
729
737
|
| preload | boolean | Enables/disables preloads globally, default: `true` |
|
|
730
|
-
| explicitLinks | boolean | Disables all anchors being intercepted and instead requires `<A>`.
|
|
738
|
+
| explicitLinks | boolean | Disables all anchors being intercepted and instead requires `<A>`. Default: `false`. (To disable interception for a specific link, set `target` to any value, e.g. `<a target="_self">`.) |
|
|
731
739
|
|
|
732
740
|
### `<A>`
|
|
733
741
|
|
|
@@ -1,27 +1,32 @@
|
|
|
1
|
+
import { type ReconcileOptions } from "solid-js/store";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* As `createAsync` and `createAsyncStore` are wrappers for `createResource`,
|
|
4
|
+
* this type allows to support `latest` field for these primitives.
|
|
5
|
+
* It will be removed in the future.
|
|
3
6
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
export type AccessorWithLatest<T> = {
|
|
8
|
+
(): T;
|
|
9
|
+
latest: T;
|
|
10
|
+
};
|
|
6
11
|
export declare function createAsync<T>(fn: (prev: T) => Promise<T>, options: {
|
|
7
12
|
name?: string;
|
|
8
13
|
initialValue: T;
|
|
9
14
|
deferStream?: boolean;
|
|
10
|
-
}):
|
|
15
|
+
}): AccessorWithLatest<T>;
|
|
11
16
|
export declare function createAsync<T>(fn: (prev: T | undefined) => Promise<T>, options?: {
|
|
12
17
|
name?: string;
|
|
13
18
|
initialValue?: T;
|
|
14
19
|
deferStream?: boolean;
|
|
15
|
-
}):
|
|
20
|
+
}): AccessorWithLatest<T | undefined>;
|
|
16
21
|
export declare function createAsyncStore<T>(fn: (prev: T) => Promise<T>, options: {
|
|
17
22
|
name?: string;
|
|
18
23
|
initialValue: T;
|
|
19
24
|
deferStream?: boolean;
|
|
20
25
|
reconcile?: ReconcileOptions;
|
|
21
|
-
}):
|
|
26
|
+
}): AccessorWithLatest<T>;
|
|
22
27
|
export declare function createAsyncStore<T>(fn: (prev: T | undefined) => Promise<T>, options?: {
|
|
23
28
|
name?: string;
|
|
24
29
|
initialValue?: T;
|
|
25
30
|
deferStream?: boolean;
|
|
26
31
|
reconcile?: ReconcileOptions;
|
|
27
|
-
}):
|
|
32
|
+
}): AccessorWithLatest<T | undefined>;
|
package/dist/data/createAsync.js
CHANGED
|
@@ -8,7 +8,13 @@ export function createAsync(fn, options) {
|
|
|
8
8
|
let resource;
|
|
9
9
|
let prev = () => !resource || resource.state === "unresolved" ? undefined : resource.latest;
|
|
10
10
|
[resource] = createResource(() => subFetch(fn, untrack(prev)), v => v, options);
|
|
11
|
-
|
|
11
|
+
const resultAccessor = (() => resource());
|
|
12
|
+
Object.defineProperty(resultAccessor, 'latest', {
|
|
13
|
+
get() {
|
|
14
|
+
return resource.latest;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
return resultAccessor;
|
|
12
18
|
}
|
|
13
19
|
export function createAsyncStore(fn, options = {}) {
|
|
14
20
|
let resource;
|
|
@@ -17,17 +23,23 @@ export function createAsyncStore(fn, options = {}) {
|
|
|
17
23
|
...options,
|
|
18
24
|
storage: (init) => createDeepSignal(init, options.reconcile)
|
|
19
25
|
});
|
|
20
|
-
|
|
26
|
+
const resultAccessor = (() => resource());
|
|
27
|
+
Object.defineProperty(resultAccessor, 'latest', {
|
|
28
|
+
get() {
|
|
29
|
+
return resource.latest;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return resultAccessor;
|
|
21
33
|
}
|
|
22
34
|
function createDeepSignal(value, options) {
|
|
23
35
|
const [store, setStore] = createStore({
|
|
24
|
-
value
|
|
36
|
+
value: structuredClone(value)
|
|
25
37
|
});
|
|
26
38
|
return [
|
|
27
39
|
() => store.value,
|
|
28
40
|
(v) => {
|
|
29
41
|
typeof v === "function" && (v = v());
|
|
30
|
-
setStore("value", reconcile(v, options));
|
|
42
|
+
setStore("value", reconcile(structuredClone(v), options));
|
|
31
43
|
return store.value;
|
|
32
44
|
}
|
|
33
45
|
];
|
package/dist/data/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createAsync, createAsyncStore } from "./createAsync.js";
|
|
1
|
+
export { createAsync, createAsyncStore, type AccessorWithLatest } from "./createAsync.js";
|
|
2
2
|
export { action, useSubmission, useSubmissions, useAction, type Action } from "./action.js";
|
|
3
3
|
export { cache, revalidate, type CachedFunction } from "./cache.js";
|
|
4
4
|
export { redirect, reload, json } from "./response.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isServer, getRequestEvent, createComponent as createComponent$1, memo, delegateEvents, spread, mergeProps as mergeProps$1, template } from 'solid-js/web';
|
|
2
|
-
import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal, createRenderEffect, on, startTransition, resetErrorBoundaries, batch, createComponent, children, mergeProps, Show, createRoot,
|
|
2
|
+
import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal, createRenderEffect, on, startTransition, resetErrorBoundaries, batch, createComponent, children, mergeProps, Show, createRoot, sharedConfig, getListener, $TRACK, splitProps, createResource } from 'solid-js';
|
|
3
3
|
import { createStore, reconcile, unwrap } from 'solid-js/store';
|
|
4
4
|
|
|
5
5
|
function createBeforeLeave() {
|
|
@@ -263,7 +263,7 @@ const useSearchParams = () => {
|
|
|
263
263
|
const location = useLocation();
|
|
264
264
|
const navigate = useNavigate();
|
|
265
265
|
const setSearchParams = (params, options) => {
|
|
266
|
-
const searchString = untrack(() =>
|
|
266
|
+
const searchString = untrack(() => mergeSearchString(location.search, params) + location.hash);
|
|
267
267
|
navigate(searchString, {
|
|
268
268
|
scroll: false,
|
|
269
269
|
resolve: false,
|
|
@@ -520,6 +520,7 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
520
520
|
}
|
|
521
521
|
return;
|
|
522
522
|
}
|
|
523
|
+
const queryOnly = !to || to[0] === "?";
|
|
523
524
|
const {
|
|
524
525
|
replace,
|
|
525
526
|
resolve,
|
|
@@ -527,11 +528,12 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
527
528
|
state: nextState
|
|
528
529
|
} = {
|
|
529
530
|
replace: false,
|
|
530
|
-
resolve:
|
|
531
|
+
resolve: !queryOnly,
|
|
531
532
|
scroll: true,
|
|
532
533
|
...options
|
|
533
534
|
};
|
|
534
|
-
|
|
535
|
+
let s;
|
|
536
|
+
const resolvedTo = resolve ? route.resolvePath(to) : resolvePath(queryOnly && (s = source().value) && s.split("?")[0] || "", to);
|
|
535
537
|
if (resolvedTo === undefined) {
|
|
536
538
|
throw new Error(`Path '${to}' is not a routable path`);
|
|
537
539
|
} else if (referrers.length >= MAX_REDIRECTS) {
|
|
@@ -840,6 +842,7 @@ function createRouter(config) {
|
|
|
840
842
|
equals: (a, b) => a.value === b.value && a.state === b.state
|
|
841
843
|
}), undefined, next => {
|
|
842
844
|
!ignore && config.set(next);
|
|
845
|
+
if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = true;
|
|
843
846
|
return next;
|
|
844
847
|
});
|
|
845
848
|
config.init && onCleanup(config.init((value = config.get()) => {
|
|
@@ -872,9 +875,8 @@ function getPath(url) {
|
|
|
872
875
|
}
|
|
873
876
|
function StaticRouter(props) {
|
|
874
877
|
let e;
|
|
875
|
-
const url = props.url || (e = getRequestEvent()) && getPath(e.request.url) || "";
|
|
876
878
|
const obj = {
|
|
877
|
-
value: props.
|
|
879
|
+
value: props.url || (e = getRequestEvent()) && getPath(e.request.url) || ""
|
|
878
880
|
};
|
|
879
881
|
return createRouterComponent({
|
|
880
882
|
signal: [() => obj, next => Object.assign(obj, next)]
|
|
@@ -1315,7 +1317,7 @@ function Router(props) {
|
|
|
1315
1317
|
const getSource = () => {
|
|
1316
1318
|
const url = window.location.pathname.replace(/^\/+/, "/") + window.location.search;
|
|
1317
1319
|
return {
|
|
1318
|
-
value:
|
|
1320
|
+
value: url + window.location.hash,
|
|
1319
1321
|
state: window.history.state
|
|
1320
1322
|
};
|
|
1321
1323
|
};
|
|
@@ -1521,11 +1523,24 @@ function Navigate(props) {
|
|
|
1521
1523
|
/**
|
|
1522
1524
|
* This is mock of the eventual Solid 2.0 primitive. It is not fully featured.
|
|
1523
1525
|
*/
|
|
1526
|
+
|
|
1527
|
+
/**
|
|
1528
|
+
* As `createAsync` and `createAsyncStore` are wrappers for `createResource`,
|
|
1529
|
+
* this type allows to support `latest` field for these primitives.
|
|
1530
|
+
* It will be removed in the future.
|
|
1531
|
+
*/
|
|
1532
|
+
|
|
1524
1533
|
function createAsync(fn, options) {
|
|
1525
1534
|
let resource;
|
|
1526
1535
|
let prev = () => !resource || resource.state === "unresolved" ? undefined : resource.latest;
|
|
1527
1536
|
[resource] = createResource(() => subFetch(fn, untrack(prev)), v => v, options);
|
|
1528
|
-
|
|
1537
|
+
const resultAccessor = () => resource();
|
|
1538
|
+
Object.defineProperty(resultAccessor, 'latest', {
|
|
1539
|
+
get() {
|
|
1540
|
+
return resource.latest;
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
return resultAccessor;
|
|
1529
1544
|
}
|
|
1530
1545
|
function createAsyncStore(fn, options = {}) {
|
|
1531
1546
|
let resource;
|
|
@@ -1534,15 +1549,21 @@ function createAsyncStore(fn, options = {}) {
|
|
|
1534
1549
|
...options,
|
|
1535
1550
|
storage: init => createDeepSignal(init, options.reconcile)
|
|
1536
1551
|
});
|
|
1537
|
-
|
|
1552
|
+
const resultAccessor = () => resource();
|
|
1553
|
+
Object.defineProperty(resultAccessor, 'latest', {
|
|
1554
|
+
get() {
|
|
1555
|
+
return resource.latest;
|
|
1556
|
+
}
|
|
1557
|
+
});
|
|
1558
|
+
return resultAccessor;
|
|
1538
1559
|
}
|
|
1539
1560
|
function createDeepSignal(value, options) {
|
|
1540
1561
|
const [store, setStore] = createStore({
|
|
1541
|
-
value
|
|
1562
|
+
value: structuredClone(value)
|
|
1542
1563
|
});
|
|
1543
1564
|
return [() => store.value, v => {
|
|
1544
1565
|
typeof v === "function" && (v = v());
|
|
1545
|
-
setStore("value", reconcile(v, options));
|
|
1566
|
+
setStore("value", reconcile(structuredClone(v), options));
|
|
1546
1567
|
return store.value;
|
|
1547
1568
|
}];
|
|
1548
1569
|
}
|
package/dist/routers/Router.js
CHANGED
|
@@ -9,7 +9,7 @@ export function Router(props) {
|
|
|
9
9
|
const getSource = () => {
|
|
10
10
|
const url = window.location.pathname.replace(/^\/+/, "/") + window.location.search;
|
|
11
11
|
return {
|
|
12
|
-
value:
|
|
12
|
+
value: url + window.location.hash,
|
|
13
13
|
state: window.history.state
|
|
14
14
|
};
|
|
15
15
|
};
|
|
@@ -6,9 +6,8 @@ function getPath(url) {
|
|
|
6
6
|
}
|
|
7
7
|
export function StaticRouter(props) {
|
|
8
8
|
let e;
|
|
9
|
-
const url = props.url || ((e = getRequestEvent()) && getPath(e.request.url)) || "";
|
|
10
9
|
const obj = {
|
|
11
|
-
value: props.
|
|
10
|
+
value: props.url || ((e = getRequestEvent()) && getPath(e.request.url)) || "",
|
|
12
11
|
};
|
|
13
12
|
return createRouterComponent({
|
|
14
13
|
signal: [() => obj, next => Object.assign(obj, next)]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createSignal, onCleanup } from "solid-js";
|
|
1
|
+
import { createSignal, onCleanup, sharedConfig } from "solid-js";
|
|
2
2
|
import { createRouterComponent } from "./components.jsx";
|
|
3
3
|
function intercept([value, setValue], get, set) {
|
|
4
4
|
return [get ? () => get(value()) : value, set ? (v) => setValue(set(v)) : setValue];
|
|
@@ -22,6 +22,8 @@ export function createRouter(config) {
|
|
|
22
22
|
equals: (a, b) => a.value === b.value && a.state === b.state
|
|
23
23
|
}), undefined, next => {
|
|
24
24
|
!ignore && config.set(next);
|
|
25
|
+
if (sharedConfig.registry && !sharedConfig.done)
|
|
26
|
+
sharedConfig.done = true;
|
|
25
27
|
return next;
|
|
26
28
|
});
|
|
27
29
|
config.init &&
|
package/dist/routing.js
CHANGED
|
@@ -41,7 +41,7 @@ export const useSearchParams = () => {
|
|
|
41
41
|
const location = useLocation();
|
|
42
42
|
const navigate = useNavigate();
|
|
43
43
|
const setSearchParams = (params, options) => {
|
|
44
|
-
const searchString = untrack(() =>
|
|
44
|
+
const searchString = untrack(() => mergeSearchString(location.search, params) + location.hash);
|
|
45
45
|
navigate(searchString, {
|
|
46
46
|
scroll: false,
|
|
47
47
|
resolve: false,
|
|
@@ -295,13 +295,17 @@ export function createRouterContext(integration, branches, getContext, options =
|
|
|
295
295
|
}
|
|
296
296
|
return;
|
|
297
297
|
}
|
|
298
|
+
const queryOnly = !to || to[0] === "?";
|
|
298
299
|
const { replace, resolve, scroll, state: nextState } = {
|
|
299
300
|
replace: false,
|
|
300
|
-
resolve:
|
|
301
|
+
resolve: !queryOnly,
|
|
301
302
|
scroll: true,
|
|
302
303
|
...options
|
|
303
304
|
};
|
|
304
|
-
|
|
305
|
+
let s;
|
|
306
|
+
const resolvedTo = resolve
|
|
307
|
+
? route.resolvePath(to)
|
|
308
|
+
: resolvePath((queryOnly && (s = source().value) && s.split("?")[0]) || "", to);
|
|
305
309
|
if (resolvedTo === undefined) {
|
|
306
310
|
throw new Error(`Path '${to}' is not a routable path`);
|
|
307
311
|
}
|
package/dist/types.d.ts
CHANGED