@astrale-os/shell-react 0.2.8 → 0.2.10-beta.2
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/dist/application/apps/app-host.d.ts +7 -15
- package/dist/application/apps/app-host.d.ts.map +1 -1
- package/dist/application/apps/app-host.js +3 -2
- package/dist/application/apps/apps.hook.d.ts +7 -4
- package/dist/application/apps/apps.hook.d.ts.map +1 -1
- package/dist/application/apps/apps.hook.js +10 -2
- package/dist/application/apps/domains.hook.d.ts +1 -1
- package/dist/application/apps/domains.hook.d.ts.map +1 -1
- package/dist/application/apps/domains.hook.js +1 -1
- package/dist/application/apps/open-app.hook.d.ts +2 -3
- package/dist/application/apps/open-app.hook.d.ts.map +1 -1
- package/dist/application/index.d.ts +2 -4
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +2 -3
- package/dist/application/spaces/space.hook.d.ts +2 -2
- package/dist/application/spaces/space.hook.d.ts.map +1 -1
- package/dist/application/spaces/space.hook.js +2 -2
- package/dist/application/spaces/spaces.hook.d.ts +2 -3
- package/dist/application/spaces/spaces.hook.d.ts.map +1 -1
- package/dist/application/spaces/spaces.hook.js +10 -3
- package/dist/auth/act-as.context.d.ts +15 -32
- package/dist/auth/act-as.context.d.ts.map +1 -1
- package/dist/auth/act-as.context.js +22 -66
- package/dist/auth/auth.hook.d.ts +1 -0
- package/dist/auth/auth.hook.d.ts.map +1 -1
- package/dist/auth/auth.hook.js +2 -22
- package/dist/auth/can.hook.d.ts +10 -38
- package/dist/auth/can.hook.d.ts.map +1 -1
- package/dist/auth/can.hook.js +35 -110
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/self.hook.d.ts +2 -2
- package/dist/auth/self.hook.d.ts.map +1 -1
- package/dist/auth/self.hook.js +0 -7
- package/dist/auth/session-kernel.d.ts +2 -3
- package/dist/auth/session-kernel.d.ts.map +1 -1
- package/dist/auth/session-kernel.js +4 -13
- package/dist/components/boundaries.d.ts +47 -0
- package/dist/components/boundaries.d.ts.map +1 -0
- package/dist/components/boundaries.js +55 -0
- package/dist/components/can.d.ts +11 -0
- package/dist/components/can.d.ts.map +1 -0
- package/dist/components/can.js +5 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +4 -0
- package/dist/components/mount-domain-frontend.d.ts +22 -0
- package/dist/components/mount-domain-frontend.d.ts.map +1 -0
- package/dist/components/mount-domain-frontend.js +85 -0
- package/dist/components/view-app.d.ts +16 -0
- package/dist/components/view-app.d.ts.map +1 -0
- package/dist/components/view-app.js +16 -0
- package/dist/graph/call/call.hook.d.ts +8 -18
- package/dist/graph/call/call.hook.d.ts.map +1 -1
- package/dist/graph/call/call.hook.js +7 -13
- package/dist/graph/call/stream.hook.d.ts +12 -20
- package/dist/graph/call/stream.hook.d.ts.map +1 -1
- package/dist/graph/call/stream.hook.js +55 -111
- package/dist/graph/graph.context.d.ts +4 -3
- package/dist/graph/graph.context.d.ts.map +1 -1
- package/dist/graph/graph.context.js +2 -8
- package/dist/graph/guards.error.d.ts +7 -8
- package/dist/graph/guards.error.d.ts.map +1 -1
- package/dist/graph/guards.error.js +11 -7
- package/dist/graph/index.d.ts +8 -16
- package/dist/graph/index.d.ts.map +1 -1
- package/dist/graph/index.js +3 -7
- package/dist/graph/memory/read/envelope.d.ts +22 -54
- package/dist/graph/memory/read/envelope.d.ts.map +1 -1
- package/dist/graph/memory/read/envelope.js +26 -20
- package/dist/graph/memory/read/idle.d.ts +1 -15
- package/dist/graph/memory/read/idle.d.ts.map +1 -1
- package/dist/graph/memory/read/idle.js +4 -13
- package/dist/graph/query-definition.hook.d.ts +11 -0
- package/dist/graph/query-definition.hook.d.ts.map +1 -0
- package/dist/graph/query-definition.hook.js +205 -0
- package/dist/graph/resource.d.ts +34 -0
- package/dist/graph/resource.d.ts.map +1 -0
- package/dist/graph/resource.js +244 -0
- package/dist/graph/store.d.ts +25 -0
- package/dist/graph/store.d.ts.map +1 -0
- package/dist/graph/store.js +69 -0
- package/dist/host/actions.hook.d.ts +34 -0
- package/dist/host/actions.hook.d.ts.map +1 -0
- package/dist/host/actions.hook.js +125 -0
- package/dist/host/components.d.ts +15 -0
- package/dist/host/components.d.ts.map +1 -0
- package/dist/host/components.js +14 -0
- package/dist/host/index.d.ts +5 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +3 -0
- package/dist/index.d.ts +26 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -31
- package/dist/intents/envelope.d.ts +7 -19
- package/dist/intents/envelope.d.ts.map +1 -1
- package/dist/intents/envelope.js +2 -3
- package/dist/intents/send-intent.hook.d.ts +5 -7
- package/dist/intents/send-intent.hook.d.ts.map +1 -1
- package/dist/intents/send-intent.hook.js +17 -75
- package/dist/navigation/adapters/adapter.d.ts +5 -0
- package/dist/navigation/adapters/adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/memory.adapter.js +4 -0
- package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/url.adapter.js +57 -10
- package/dist/navigation/codec.d.ts +60 -0
- package/dist/navigation/codec.d.ts.map +1 -0
- package/dist/navigation/codec.js +121 -0
- package/dist/navigation/history.d.ts +11 -9
- package/dist/navigation/history.d.ts.map +1 -1
- package/dist/navigation/history.js +6 -8
- package/dist/navigation/hooks/ancestors.hook.d.ts +5 -7
- package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/ancestors.hook.js +7 -51
- package/dist/navigation/hooks/location.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/location.hook.js +4 -6
- package/dist/navigation/hooks/scope.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/scope.hook.js +4 -6
- package/dist/navigation/index.d.ts +4 -2
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +2 -1
- package/dist/navigation/link.d.ts +12 -0
- package/dist/navigation/link.d.ts.map +1 -1
- package/dist/navigation/link.js +13 -2
- package/dist/navigation/location.d.ts +13 -40
- package/dist/navigation/location.d.ts.map +1 -1
- package/dist/navigation/location.js +14 -76
- package/dist/navigation/scope.context.d.ts +17 -26
- package/dist/navigation/scope.context.d.ts.map +1 -1
- package/dist/navigation/scope.context.js +140 -108
- package/dist/navigation/snapshot.d.ts +14 -19
- package/dist/navigation/snapshot.d.ts.map +1 -1
- package/dist/navigation/snapshot.js +48 -44
- package/dist/schema/action.hook.d.ts +44 -0
- package/dist/schema/action.hook.d.ts.map +1 -0
- package/dist/schema/action.hook.js +72 -0
- package/dist/schema/domain.hook.d.ts +12 -7
- package/dist/schema/domain.hook.d.ts.map +1 -1
- package/dist/schema/domain.hook.js +101 -4
- package/dist/schema/index.d.ts +9 -8
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +5 -7
- package/dist/schema/kernel.hook.d.ts +4 -9
- package/dist/schema/kernel.hook.d.ts.map +1 -1
- package/dist/schema/kernel.hook.js +4 -6
- package/dist/schema/mutation.hook.d.ts +9 -0
- package/dist/schema/mutation.hook.d.ts.map +1 -0
- package/dist/schema/mutation.hook.js +41 -0
- package/dist/schema/object.hook.d.ts +16 -0
- package/dist/schema/object.hook.d.ts.map +1 -0
- package/dist/schema/object.hook.js +46 -0
- package/dist/schema/relation.hook.d.ts +46 -0
- package/dist/schema/relation.hook.d.ts.map +1 -0
- package/dist/schema/relation.hook.js +136 -0
- package/dist/selection/live.d.ts +9 -17
- package/dist/selection/live.d.ts.map +1 -1
- package/dist/selection/live.js +65 -112
- package/dist/selection/scope.context.js +5 -4
- package/dist/session/boot/boot.d.ts +1 -13
- package/dist/session/boot/boot.d.ts.map +1 -1
- package/dist/session/boot/boot.js +9 -27
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/kernel-instance.hook.d.ts +1 -4
- package/dist/session/kernel-instance.hook.d.ts.map +1 -1
- package/dist/session/kernel-instance.hook.js +1 -5
- package/dist/session/provider.d.ts +9 -23
- package/dist/session/provider.d.ts.map +1 -1
- package/dist/session/provider.js +29 -75
- package/dist/session/session.context.d.ts +5 -0
- package/dist/session/session.context.d.ts.map +1 -1
- package/dist/window/adopt.d.ts +0 -1
- package/dist/window/adopt.d.ts.map +1 -1
- package/dist/window/hooks/target-node.hook.d.ts +10 -6
- package/dist/window/hooks/target-node.hook.d.ts.map +1 -1
- package/dist/window/hooks/target-node.hook.js +14 -72
- package/dist/window/hooks/views-for.hook.d.ts +4 -3
- package/dist/window/hooks/views-for.hook.d.ts.map +1 -1
- package/dist/window/hooks/views-for.hook.js +6 -22
- package/dist/window/hooks/windows.hook.d.ts.map +1 -1
- package/dist/window/hooks/windows.hook.js +3 -4
- package/dist/window/host.d.ts +11 -11
- package/dist/window/host.d.ts.map +1 -1
- package/dist/window/host.js +38 -54
- package/dist/window/hub.d.ts +2 -0
- package/dist/window/hub.d.ts.map +1 -1
- package/dist/window/hub.js +33 -0
- package/dist/window/index.d.ts +3 -3
- package/dist/window/index.d.ts.map +1 -1
- package/dist/window/index.js +2 -2
- package/dist/window/lifecycle/mount.d.ts +5 -44
- package/dist/window/lifecycle/mount.d.ts.map +1 -1
- package/dist/window/lifecycle/mount.js +14 -120
- package/dist/window/lifecycle/states.d.ts +0 -5
- package/dist/window/lifecycle/states.d.ts.map +1 -1
- package/dist/window/stage.d.ts.map +1 -1
- package/dist/window/stage.js +1 -0
- package/package.json +9 -8
- package/src/application/apps/app-host.tsx +17 -18
- package/src/application/apps/apps.hook.ts +13 -6
- package/src/application/apps/domains.hook.ts +1 -1
- package/src/application/apps/open-app.hook.ts +3 -4
- package/src/application/index.ts +4 -6
- package/src/application/spaces/space.hook.ts +5 -6
- package/src/application/spaces/spaces.hook.ts +14 -9
- package/src/auth/act-as.context.tsx +37 -91
- package/src/auth/auth.hook.ts +2 -30
- package/src/auth/can.hook.ts +44 -135
- package/src/auth/index.ts +1 -0
- package/src/auth/self.hook.ts +2 -9
- package/src/auth/session-kernel.ts +6 -16
- package/src/components/boundaries.tsx +113 -0
- package/src/components/can.tsx +16 -0
- package/src/components/index.ts +14 -0
- package/src/components/mount-domain-frontend.tsx +158 -0
- package/src/components/view-app.tsx +49 -0
- package/src/graph/call/call.hook.ts +22 -27
- package/src/graph/call/stream.hook.ts +66 -143
- package/src/graph/graph.context.ts +6 -11
- package/src/graph/guards.error.ts +17 -55
- package/src/graph/index.ts +23 -17
- package/src/graph/memory/read/envelope.ts +40 -65
- package/src/graph/memory/read/idle.ts +5 -18
- package/src/graph/query-definition.hook.ts +270 -0
- package/src/graph/resource.ts +358 -0
- package/src/graph/store.ts +97 -0
- package/src/host/actions.hook.ts +165 -0
- package/src/host/components.tsx +29 -0
- package/src/host/index.ts +17 -0
- package/src/index.ts +137 -123
- package/src/intents/envelope.ts +7 -23
- package/src/intents/send-intent.hook.ts +24 -79
- package/src/navigation/adapters/adapter.ts +3 -0
- package/src/navigation/adapters/memory.adapter.ts +4 -0
- package/src/navigation/adapters/url.adapter.ts +48 -8
- package/src/navigation/codec.ts +190 -0
- package/src/navigation/history.ts +20 -11
- package/src/navigation/hooks/ancestors.hook.ts +10 -60
- package/src/navigation/hooks/location.hook.ts +4 -6
- package/src/navigation/hooks/scope.hook.ts +4 -6
- package/src/navigation/index.ts +18 -2
- package/src/navigation/link.tsx +27 -2
- package/src/navigation/location.ts +26 -93
- package/src/navigation/scope.context.tsx +151 -136
- package/src/navigation/snapshot.ts +69 -50
- package/src/schema/action.hook.ts +146 -0
- package/src/schema/domain.hook.ts +127 -11
- package/src/schema/index.ts +9 -30
- package/src/schema/kernel.hook.ts +6 -13
- package/src/schema/mutation.hook.ts +63 -0
- package/src/schema/object.hook.ts +85 -0
- package/src/schema/relation.hook.ts +253 -0
- package/src/selection/live.ts +75 -125
- package/src/selection/scope.context.tsx +4 -4
- package/src/session/boot/boot.ts +8 -33
- package/src/session/index.ts +1 -0
- package/src/session/kernel-instance.hook.ts +2 -11
- package/src/session/provider.tsx +34 -103
- package/src/session/session.context.ts +6 -0
- package/src/window/adopt.ts +0 -1
- package/src/window/hooks/target-node.hook.ts +20 -85
- package/src/window/hooks/views-for.hook.ts +12 -25
- package/src/window/hooks/windows.hook.ts +3 -4
- package/src/window/host.tsx +51 -68
- package/src/window/hub.ts +33 -0
- package/src/window/index.ts +4 -4
- package/src/window/lifecycle/mount.ts +15 -160
- package/src/window/lifecycle/states.ts +1 -5
- package/src/window/stage.tsx +1 -0
- package/dist/application/roles.hook.d.ts +0 -7
- package/dist/application/roles.hook.d.ts.map +0 -1
- package/dist/application/roles.hook.js +0 -23
- package/dist/graph/memory/base.d.ts +0 -21
- package/dist/graph/memory/base.d.ts.map +0 -1
- package/dist/graph/memory/base.js +0 -33
- package/dist/graph/memory/read/read.d.ts +0 -9
- package/dist/graph/memory/read/read.d.ts.map +0 -1
- package/dist/graph/memory/read/read.js +0 -87
- package/dist/graph/memory/scope.d.ts +0 -7
- package/dist/graph/memory/scope.d.ts.map +0 -1
- package/dist/graph/memory/scope.js +0 -25
- package/dist/graph/mutate/move.hook.d.ts +0 -7
- package/dist/graph/mutate/move.hook.d.ts.map +0 -1
- package/dist/graph/mutate/move.hook.js +0 -49
- package/dist/graph/mutate/mutate.hook.d.ts +0 -17
- package/dist/graph/mutate/mutate.hook.d.ts.map +0 -1
- package/dist/graph/mutate/mutate.hook.js +0 -45
- package/dist/graph/query/children.hook.d.ts +0 -29
- package/dist/graph/query/children.hook.d.ts.map +0 -1
- package/dist/graph/query/children.hook.js +0 -64
- package/dist/graph/query/graph.hook.d.ts +0 -9
- package/dist/graph/query/graph.hook.d.ts.map +0 -1
- package/dist/graph/query/graph.hook.js +0 -5
- package/dist/graph/query/neighbors.hook.d.ts +0 -7
- package/dist/graph/query/neighbors.hook.d.ts.map +0 -1
- package/dist/graph/query/neighbors.hook.js +0 -104
- package/dist/graph/query/node.hook.d.ts +0 -14
- package/dist/graph/query/node.hook.d.ts.map +0 -1
- package/dist/graph/query/node.hook.js +0 -43
- package/dist/graph/query/query.hook.d.ts +0 -14
- package/dist/graph/query/query.hook.d.ts.map +0 -1
- package/dist/graph/query/query.hook.js +0 -23
- package/dist/schema/bind-read.d.ts +0 -37
- package/dist/schema/bind-read.d.ts.map +0 -1
- package/dist/schema/bind-read.js +0 -205
- package/dist/schema/binding.d.ts +0 -21
- package/dist/schema/binding.d.ts.map +0 -1
- package/dist/schema/binding.js +0 -99
- package/dist/schema/function.hook.d.ts +0 -9
- package/dist/schema/function.hook.d.ts.map +0 -1
- package/dist/schema/function.hook.js +0 -40
- package/dist/schema/method.hook.d.ts +0 -14
- package/dist/schema/method.hook.d.ts.map +0 -1
- package/dist/schema/method.hook.js +0 -49
- package/dist/schema/tag.d.ts +0 -11
- package/dist/schema/tag.d.ts.map +0 -1
- package/dist/schema/tag.js +0 -11
- package/dist/schema/types.d.ts +0 -73
- package/dist/schema/types.d.ts.map +0 -1
- package/dist/schema/types.js +0 -1
- package/dist/schema/write.d.ts +0 -16
- package/dist/schema/write.d.ts.map +0 -1
- package/dist/schema/write.js +0 -56
- package/src/application/roles.hook.ts +0 -41
- package/src/graph/memory/base.ts +0 -50
- package/src/graph/memory/read/read.ts +0 -103
- package/src/graph/memory/scope.ts +0 -29
- package/src/graph/mutate/move.hook.ts +0 -70
- package/src/graph/mutate/mutate.hook.ts +0 -69
- package/src/graph/query/children.hook.ts +0 -136
- package/src/graph/query/graph.hook.ts +0 -13
- package/src/graph/query/neighbors.hook.ts +0 -159
- package/src/graph/query/node.hook.ts +0 -83
- package/src/graph/query/query.hook.ts +0 -42
- package/src/schema/bind-read.ts +0 -319
- package/src/schema/binding.ts +0 -146
- package/src/schema/function.hook.ts +0 -68
- package/src/schema/method.hook.ts +0 -103
- package/src/schema/tag.ts +0 -19
- package/src/schema/types.ts +0 -150
- package/src/schema/write.ts +0 -96
|
@@ -1,34 +1,69 @@
|
|
|
1
|
-
|
|
1
|
+
import { NodePath } from '@astrale-os/sdk/graph/path';
|
|
2
|
+
import { Key } from '@astrale-os/sdk/schema';
|
|
3
|
+
const VIEW_KEY = 'astrale.view';
|
|
4
|
+
const PARAM_PREFIX = 'astrale.param.';
|
|
2
5
|
/** History-API adapter — the location lives in the query string. */
|
|
3
6
|
export function urlAdapter(opts) {
|
|
4
|
-
const param = opts?.param ?? 'node';
|
|
7
|
+
const param = opts?.param ?? 'astrale.node';
|
|
5
8
|
const hasWindow = () => typeof window !== 'undefined';
|
|
6
9
|
const build = (loc) => {
|
|
7
10
|
const url = new URL(window.location.href);
|
|
8
|
-
const sp =
|
|
11
|
+
const sp = url.searchParams;
|
|
9
12
|
sp.set(param, loc.node);
|
|
10
13
|
if (loc.view !== undefined)
|
|
11
14
|
sp.set(VIEW_KEY, loc.view);
|
|
15
|
+
else
|
|
16
|
+
sp.delete(VIEW_KEY);
|
|
17
|
+
for (const key of sp.keys())
|
|
18
|
+
if (key.startsWith(PARAM_PREFIX))
|
|
19
|
+
sp.delete(key);
|
|
12
20
|
for (const [k, v] of Object.entries(loc.params ?? {})) {
|
|
13
|
-
if (k
|
|
14
|
-
|
|
21
|
+
if (isSensitive(k))
|
|
22
|
+
throw new TypeError(`Navigation param '${k}' is sensitive.`);
|
|
23
|
+
sp.set(`${PARAM_PREFIX}${k}`, v);
|
|
15
24
|
}
|
|
16
25
|
url.search = sp.toString();
|
|
17
26
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
18
27
|
};
|
|
28
|
+
const clear = () => {
|
|
29
|
+
const url = new URL(window.location.href);
|
|
30
|
+
const sp = url.searchParams;
|
|
31
|
+
sp.delete(param);
|
|
32
|
+
sp.delete(VIEW_KEY);
|
|
33
|
+
for (const key of sp.keys())
|
|
34
|
+
if (key.startsWith(PARAM_PREFIX))
|
|
35
|
+
sp.delete(key);
|
|
36
|
+
url.search = sp.toString();
|
|
37
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
38
|
+
};
|
|
19
39
|
return {
|
|
40
|
+
kind: 'browser',
|
|
20
41
|
read() {
|
|
21
42
|
if (!hasWindow())
|
|
22
43
|
return null;
|
|
23
44
|
const sp = new URL(window.location.href).searchParams;
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
45
|
+
const rawNode = sp.get(param);
|
|
46
|
+
if (rawNode === null)
|
|
26
47
|
return null;
|
|
27
|
-
|
|
48
|
+
let node;
|
|
49
|
+
let view;
|
|
50
|
+
try {
|
|
51
|
+
node = NodePath(rawNode);
|
|
52
|
+
const rawView = sp.get(VIEW_KEY);
|
|
53
|
+
if (rawView !== null) {
|
|
54
|
+
const admitted = Key(rawView);
|
|
55
|
+
if (!Key.ref(admitted).startsWith('view.'))
|
|
56
|
+
throw new TypeError('Invalid View key.');
|
|
57
|
+
view = admitted;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
28
63
|
const params = {};
|
|
29
64
|
for (const [k, v] of sp) {
|
|
30
|
-
if (k
|
|
31
|
-
params[k] = v;
|
|
65
|
+
if (k.startsWith(PARAM_PREFIX))
|
|
66
|
+
params[k.slice(PARAM_PREFIX.length)] = v;
|
|
32
67
|
}
|
|
33
68
|
return {
|
|
34
69
|
node,
|
|
@@ -45,6 +80,15 @@ export function urlAdapter(opts) {
|
|
|
45
80
|
else
|
|
46
81
|
window.history.pushState(null, '', href);
|
|
47
82
|
},
|
|
83
|
+
clear({ replace }) {
|
|
84
|
+
if (!hasWindow())
|
|
85
|
+
return;
|
|
86
|
+
const href = clear();
|
|
87
|
+
if (replace)
|
|
88
|
+
window.history.replaceState(null, '', href);
|
|
89
|
+
else
|
|
90
|
+
window.history.pushState(null, '', href);
|
|
91
|
+
},
|
|
48
92
|
subscribe(cb) {
|
|
49
93
|
if (!hasWindow())
|
|
50
94
|
return () => undefined;
|
|
@@ -57,3 +101,6 @@ export function urlAdapter(opts) {
|
|
|
57
101
|
},
|
|
58
102
|
};
|
|
59
103
|
}
|
|
104
|
+
function isSensitive(key) {
|
|
105
|
+
return /token|credential|authorization|secret/i.test(key);
|
|
106
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Key } from '@astrale-os/sdk/schema';
|
|
2
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import { Path } from '@astrale-os/sdk/graph/path';
|
|
4
|
+
import type { NavAdapter } from './adapters/adapter.js';
|
|
5
|
+
import type { NavSnapshot, SerializedLocation } from './history.js';
|
|
6
|
+
export interface NavigationParam<Value> {
|
|
7
|
+
encode(value: Value): string;
|
|
8
|
+
decode(value: string | undefined): Value;
|
|
9
|
+
}
|
|
10
|
+
export declare function pathParam(_name: string): NavigationParam<Path>;
|
|
11
|
+
export declare function enumParam<const Values extends readonly [string, ...string[]]>(values: Values, fallback: Values[number]): NavigationParam<Values[number]>;
|
|
12
|
+
export type NavigationParams = Readonly<Record<string, NavigationParam<unknown>>>;
|
|
13
|
+
export interface LocationDefinition<Target, Params extends NavigationParams> {
|
|
14
|
+
readonly view: Key.View;
|
|
15
|
+
readonly target: NavigationParam<Target>;
|
|
16
|
+
readonly params: Params;
|
|
17
|
+
}
|
|
18
|
+
export declare function location<Target, const Params extends NavigationParams = Readonly<Record<never, never>>>(input: {
|
|
19
|
+
readonly view: Key.View | {
|
|
20
|
+
readonly key: Key.View;
|
|
21
|
+
};
|
|
22
|
+
readonly target: NavigationParam<Target>;
|
|
23
|
+
readonly params?: Params;
|
|
24
|
+
}): LocationDefinition<Target, Params>;
|
|
25
|
+
type ValueOf<Codec> = Codec extends NavigationParam<infer Value> ? Value : never;
|
|
26
|
+
type RouteTarget<Routes extends Readonly<Record<string, LocationDefinition<unknown, NavigationParams>>>> = {
|
|
27
|
+
[Name in keyof Routes]: Readonly<{
|
|
28
|
+
name: Name;
|
|
29
|
+
target: ValueOf<Routes[Name]['target']>;
|
|
30
|
+
params: Readonly<{
|
|
31
|
+
[Param in keyof Routes[Name]['params']]: ValueOf<Routes[Name]['params'][Param]>;
|
|
32
|
+
}>;
|
|
33
|
+
}>;
|
|
34
|
+
}[keyof Routes];
|
|
35
|
+
export type NavigationRoutes = Readonly<Record<string, LocationDefinition<unknown, NavigationParams>>>;
|
|
36
|
+
export interface NavigationDefinition<Routes extends NavigationRoutes = NavigationRoutes> {
|
|
37
|
+
readonly routes: Routes;
|
|
38
|
+
encode(target: RouteTarget<Routes>): SerializedLocation;
|
|
39
|
+
decode(location: SerializedLocation): RouteTarget<Routes> | null;
|
|
40
|
+
admit(location: SerializedLocation): SerializedLocation | null;
|
|
41
|
+
}
|
|
42
|
+
export declare function defineNavigation<const Routes extends NavigationRoutes>(routes: Routes): NavigationDefinition<Routes>;
|
|
43
|
+
export declare function NavigationScope<Routes extends NavigationRoutes>(props: {
|
|
44
|
+
readonly navigation: NavigationDefinition<Routes>;
|
|
45
|
+
readonly adapter?: NavAdapter;
|
|
46
|
+
readonly restore?: NavSnapshot;
|
|
47
|
+
readonly initial?: RouteTarget<Routes>;
|
|
48
|
+
readonly children: ReactNode;
|
|
49
|
+
}): ReactElement;
|
|
50
|
+
export declare function useNavigation<Routes extends NavigationRoutes>(navigation: NavigationDefinition<Routes>): Readonly<{
|
|
51
|
+
location: RouteTarget<Routes> | null;
|
|
52
|
+
push: (target: RouteTarget<Routes>) => void;
|
|
53
|
+
replace: (target: RouteTarget<Routes>) => void;
|
|
54
|
+
back: () => void;
|
|
55
|
+
forward: () => void;
|
|
56
|
+
snapshot: () => NavSnapshot;
|
|
57
|
+
}>;
|
|
58
|
+
export type NavigationTarget<Definition> = Definition extends NavigationDefinition<infer Routes> ? RouteTarget<Routes> : never;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/navigation/codec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Path } from '@astrale-os/sdk/graph/path';
|
|
2
|
+
import { Key as admitKey } from '@astrale-os/sdk/schema';
|
|
3
|
+
import { createElement } from 'react';
|
|
4
|
+
import { NavScope } from './scope.context.js';
|
|
5
|
+
import { useNavCtx } from './scope.context.js';
|
|
6
|
+
import { useHistoryVersion } from './scope.context.js';
|
|
7
|
+
export function pathParam(_name) {
|
|
8
|
+
return Object.freeze({
|
|
9
|
+
encode: (value) => Path.from(value).raw,
|
|
10
|
+
decode(value) {
|
|
11
|
+
if (value === undefined)
|
|
12
|
+
throw new TypeError('Navigation target is missing.');
|
|
13
|
+
return Path.parse(value);
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function enumParam(values, fallback) {
|
|
18
|
+
if (!values.includes(fallback))
|
|
19
|
+
throw new TypeError('Navigation enum fallback is not admitted.');
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
encode(value) {
|
|
22
|
+
if (!values.includes(value))
|
|
23
|
+
throw new TypeError(`Invalid navigation enum value '${value}'.`);
|
|
24
|
+
return value;
|
|
25
|
+
},
|
|
26
|
+
decode(value) {
|
|
27
|
+
if (value === undefined)
|
|
28
|
+
return fallback;
|
|
29
|
+
if (!values.includes(value))
|
|
30
|
+
throw new TypeError(`Invalid navigation enum value '${value}'.`);
|
|
31
|
+
return value;
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export function location(input) {
|
|
36
|
+
return Object.freeze({
|
|
37
|
+
view: viewKey(typeof input.view === 'string' ? input.view : input.view.key),
|
|
38
|
+
target: input.target,
|
|
39
|
+
params: Object.freeze({ ...input.params }),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export function defineNavigation(routes) {
|
|
43
|
+
const names = Object.keys(routes).sort();
|
|
44
|
+
const byView = new Map(names.map((name) => [routes[name].view, name]));
|
|
45
|
+
if (byView.size !== names.length)
|
|
46
|
+
throw new TypeError('Navigation Views must be unique.');
|
|
47
|
+
const definition = {
|
|
48
|
+
routes: Object.freeze({ ...routes }),
|
|
49
|
+
encode(target) {
|
|
50
|
+
const route = routes[target.name];
|
|
51
|
+
if (route === undefined)
|
|
52
|
+
throw new TypeError(`Unknown navigation location '${String(target.name)}'.`);
|
|
53
|
+
const params = Object.fromEntries(Object.entries(route.params).map(([name, codec]) => [
|
|
54
|
+
name,
|
|
55
|
+
codec.encode(target.params[name]),
|
|
56
|
+
]));
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
node: Path.parse(route.target.encode(target.target)).raw,
|
|
59
|
+
view: route.view,
|
|
60
|
+
...(Object.keys(params).length === 0 ? {} : { params: Object.freeze(params) }),
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
decode(serialized) {
|
|
64
|
+
if (serialized.view === undefined)
|
|
65
|
+
return null;
|
|
66
|
+
const name = byView.get(serialized.view);
|
|
67
|
+
if (name === undefined)
|
|
68
|
+
return null;
|
|
69
|
+
const route = routes[name];
|
|
70
|
+
try {
|
|
71
|
+
const params = Object.fromEntries(Object.entries(route.params).map(([param, codec]) => [
|
|
72
|
+
param,
|
|
73
|
+
codec.decode(serialized.params?.[param]),
|
|
74
|
+
]));
|
|
75
|
+
if (Object.keys(serialized.params ?? {}).some((param) => !(param in route.params)))
|
|
76
|
+
return null;
|
|
77
|
+
return Object.freeze({
|
|
78
|
+
name,
|
|
79
|
+
target: route.target.decode(serialized.node),
|
|
80
|
+
params: Object.freeze(params),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
admit(serialized) {
|
|
88
|
+
const decoded = definition.decode(serialized);
|
|
89
|
+
return decoded === null ? null : definition.encode(decoded);
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
return Object.freeze(definition);
|
|
93
|
+
}
|
|
94
|
+
export function NavigationScope(props) {
|
|
95
|
+
return createElement(NavScope, {
|
|
96
|
+
...(props.adapter === undefined ? {} : { adapter: props.adapter }),
|
|
97
|
+
...(props.restore === undefined ? {} : { restore: props.restore }),
|
|
98
|
+
...(props.initial === undefined ? {} : { initial: props.navigation.encode(props.initial) }),
|
|
99
|
+
admit: props.navigation.admit,
|
|
100
|
+
children: props.children,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
export function useNavigation(navigation) {
|
|
104
|
+
const context = useNavCtx();
|
|
105
|
+
useHistoryVersion(context.history);
|
|
106
|
+
const current = context.history.current;
|
|
107
|
+
return Object.freeze({
|
|
108
|
+
location: current === null ? null : navigation.decode(current),
|
|
109
|
+
push: (target) => context.navigate(navigation.encode(target)),
|
|
110
|
+
replace: (target) => context.navigate(navigation.encode(target), { replace: true }),
|
|
111
|
+
back: context.navigate.back,
|
|
112
|
+
forward: context.navigate.forward,
|
|
113
|
+
snapshot: () => context.history.snapshot(),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function viewKey(input) {
|
|
117
|
+
const key = admitKey(input);
|
|
118
|
+
if (!admitKey.ref(key).startsWith('view.'))
|
|
119
|
+
throw new TypeError(`Invalid View key '${input}'.`);
|
|
120
|
+
return key;
|
|
121
|
+
}
|
|
@@ -4,17 +4,19 @@
|
|
|
4
4
|
* (`SerializedLocation`/`NavSnapshot` + equality/clone), and the seed precedence.
|
|
5
5
|
* Source of truth for back/forward; the adapter is a projection sink around it.
|
|
6
6
|
*/
|
|
7
|
+
import type { NodePath } from '@astrale-os/sdk/graph/path';
|
|
8
|
+
import type { Key } from '@astrale-os/sdk/schema';
|
|
7
9
|
/** The serializable projection persisted in history / URLs / snapshots. */
|
|
8
10
|
export interface SerializedLocation {
|
|
9
|
-
node:
|
|
10
|
-
view?:
|
|
11
|
-
params?: Record<string, string
|
|
11
|
+
readonly node: NodePath;
|
|
12
|
+
readonly view?: Key.View;
|
|
13
|
+
readonly params?: Readonly<Record<string, string>>;
|
|
12
14
|
}
|
|
13
15
|
/** A versioned history snapshot — round-trips through `NavScope.restore`. */
|
|
14
16
|
export interface NavSnapshot {
|
|
15
|
-
v: 1;
|
|
16
|
-
entries: SerializedLocation[];
|
|
17
|
-
cursor: number;
|
|
17
|
+
readonly v: 1;
|
|
18
|
+
readonly entries: readonly SerializedLocation[];
|
|
19
|
+
readonly cursor: number;
|
|
18
20
|
}
|
|
19
21
|
/** Structural equality of two serialized locations (node + view + params). */
|
|
20
22
|
export declare function sameLocation(a: SerializedLocation, b: SerializedLocation): boolean;
|
|
@@ -42,7 +44,7 @@ export declare class NavHistory {
|
|
|
42
44
|
*/
|
|
43
45
|
syncExternal(loc: SerializedLocation): boolean;
|
|
44
46
|
/** Replace the whole stack (restore revalidation prune). */
|
|
45
|
-
reset(entries: SerializedLocation[], cursor: number): void;
|
|
47
|
+
reset(entries: readonly SerializedLocation[], cursor: number): void;
|
|
46
48
|
private emit;
|
|
47
49
|
}
|
|
48
50
|
/**
|
|
@@ -54,8 +56,8 @@ export declare class NavHistory {
|
|
|
54
56
|
* history).
|
|
55
57
|
*/
|
|
56
58
|
export declare function seedEntries(fromAdapter: SerializedLocation | null, restore: {
|
|
57
|
-
entries: SerializedLocation[];
|
|
58
|
-
cursor: number;
|
|
59
|
+
readonly entries: readonly SerializedLocation[];
|
|
60
|
+
readonly cursor: number;
|
|
59
61
|
} | undefined, initialSerialized: SerializedLocation | null): {
|
|
60
62
|
entries: SerializedLocation[];
|
|
61
63
|
cursor: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/navigation/history.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/navigation/history.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAA;AAEjD,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAA;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACnD;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAA;IACb,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAA;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAElF;AAaD,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,GAAG,EAAE,kBAAkB,GAAG,kBAAkB,CAMzE;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAI;IACnB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,YAAY,OAAO,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,MAAM,EAGxD;IAED,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAG1C;IAED,UAAU,IAAI,MAAM,CAEnB;IAED,IAAI,OAAO,IAAI,kBAAkB,GAAG,IAAI,CAEvC;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,QAAQ,IAAI,WAAW,CAMtB;IAED,mFAAmF;IACnF,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAYvD;IAED,IAAI,IAAI,OAAO,CAKd;IAED,OAAO,IAAI,OAAO,CAKjB;IAED;;;OAGG;IACH,YAAY,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAgB7C;IAED,4DAA4D;IAC5D,KAAK,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAIlE;IAED,OAAO,CAAC,IAAI;CAIb;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,kBAAkB,GAAG,IAAI,EACtC,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACjG,iBAAiB,EAAE,kBAAkB,GAAG,IAAI,GAC3C;IAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAcnD"}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The per-scope history model (API §8.2) — a framework-free entries+cursor stack
|
|
3
|
-
* with a version counter for `useSyncExternalStore`, its serialized entry shape
|
|
4
|
-
* (`SerializedLocation`/`NavSnapshot` + equality/clone), and the seed precedence.
|
|
5
|
-
* Source of truth for back/forward; the adapter is a projection sink around it.
|
|
6
|
-
*/
|
|
7
1
|
/** Structural equality of two serialized locations (node + view + params). */
|
|
8
2
|
export function sameLocation(a, b) {
|
|
9
3
|
return a.node === b.node && a.view === b.view && sameParams(a.params, b.params);
|
|
@@ -51,7 +45,11 @@ export class NavHistory {
|
|
|
51
45
|
return this.cursor >= 0 && this.cursor < this.entries.length - 1;
|
|
52
46
|
}
|
|
53
47
|
snapshot() {
|
|
54
|
-
return
|
|
48
|
+
return Object.freeze({
|
|
49
|
+
v: 1,
|
|
50
|
+
entries: Object.freeze(this.entries.map(cloneLocation)),
|
|
51
|
+
cursor: this.cursor,
|
|
52
|
+
});
|
|
55
53
|
}
|
|
56
54
|
/** Push (or replace the current entry with) a location. No-op on same location. */
|
|
57
55
|
push(loc, replace) {
|
|
@@ -107,7 +105,7 @@ export class NavHistory {
|
|
|
107
105
|
}
|
|
108
106
|
/** Replace the whole stack (restore revalidation prune). */
|
|
109
107
|
reset(entries, cursor) {
|
|
110
|
-
this.entries = entries;
|
|
108
|
+
this.entries = [...entries];
|
|
111
109
|
this.cursor = cursor;
|
|
112
110
|
this.emit();
|
|
113
111
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Node } from '@astrale-os/sdk/graph/node';
|
|
2
|
+
import type { PathLike } from '@astrale-os/sdk/graph/path';
|
|
2
3
|
import type { ReadState } from '../../graph/memory/read/envelope.js';
|
|
3
|
-
import type { Node } from '../location.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* node/path makes it usable outside a scope. The chain drops any ancestor whose
|
|
8
|
-
* record is masked/absent.
|
|
5
|
+
* Retained public concern with an explicit failed state: V2 has no implicit
|
|
6
|
+
* slash-tree ancestry. Callers must query a declared Edge Class instead.
|
|
9
7
|
*/
|
|
10
|
-
export declare function useAncestors(
|
|
8
|
+
export declare function useAncestors(_node?: Node | PathLike): ReadState & {
|
|
11
9
|
readonly chain: readonly Node[];
|
|
12
10
|
};
|
|
13
11
|
//# sourceMappingURL=ancestors.hook.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ancestors.hook.d.ts","sourceRoot":"","sources":["../../../src/navigation/hooks/ancestors.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ancestors.hook.d.ts","sourceRoot":"","sources":["../../../src/navigation/hooks/ancestors.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAMpE;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,CAAC,EAAE,IAAI,GAAG,QAAQ,GACtB,SAAS,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;CAAE,CAKjD"}
|
|
@@ -1,56 +1,12 @@
|
|
|
1
|
+
import { unsupportedReadState } from '../../graph/memory/read/envelope.js';
|
|
2
|
+
const EMPTY_CHAIN = Object.freeze([]);
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* passing a node/path makes it usable outside a scope. Drops any masked ancestor.
|
|
5
|
-
*/
|
|
6
|
-
import { useMemo } from 'react';
|
|
7
|
-
import { idleReadState } from '../../graph/memory/read/idle.js';
|
|
8
|
-
import { useMemory } from '../../graph/memory/scope.js';
|
|
9
|
-
import { chainPaths, pathHint, pathOf } from '../location.js';
|
|
10
|
-
import { useHistoryVersion, useOptionalNavCtx, useMemoryShape } from '../scope.context.js';
|
|
11
|
-
import { serializeTarget } from '../snapshot.js';
|
|
12
|
-
/**
|
|
13
|
-
* The root-first ancestor chain (inclusive of the node itself), live: a move
|
|
14
|
-
* re-renders it. `node` defaults to the nearest scope's location node; passing a
|
|
15
|
-
* node/path makes it usable outside a scope. The chain drops any ancestor whose
|
|
16
|
-
* record is masked/absent.
|
|
4
|
+
* Retained public concern with an explicit failed state: V2 has no implicit
|
|
5
|
+
* slash-tree ancestry. Callers must query a declared Edge Class instead.
|
|
17
6
|
*/
|
|
18
|
-
export function useAncestors(
|
|
19
|
-
const memory = useMemory();
|
|
20
|
-
const ctx = useOptionalNavCtx();
|
|
21
|
-
useHistoryVersion(ctx?.history ?? null);
|
|
22
|
-
const baseRef = node !== undefined ? serializeTarget(node).node : (ctx?.history.current?.node ?? null);
|
|
23
|
-
const baseResult = useMemoryShape(memory, baseRef);
|
|
24
|
-
const basePath = baseResult?.node ? pathOf(baseResult.node) : pathHint(baseRef ?? '');
|
|
25
|
-
const paths = useMemo(() => (basePath !== '' ? chainPaths(basePath) : EMPTY_PATHS), [basePath]);
|
|
26
|
-
const shape = useMemo(() => (basePath !== '' ? (q) => q.from(...chainPaths(basePath)) : null), [basePath]);
|
|
27
|
-
const chainResult = useMemoryShape(memory, shape);
|
|
28
|
-
const chain = useMemo(() => {
|
|
29
|
-
if (chainResult === null)
|
|
30
|
-
return EMPTY_CHAIN;
|
|
31
|
-
const byPath = new Map();
|
|
32
|
-
for (const n of chainResult.roots)
|
|
33
|
-
byPath.set(pathOf(n), n);
|
|
34
|
-
const out = [];
|
|
35
|
-
for (const p of paths) {
|
|
36
|
-
const hit = byPath.get(p);
|
|
37
|
-
if (hit !== undefined)
|
|
38
|
-
out.push(hit);
|
|
39
|
-
}
|
|
40
|
-
return out;
|
|
41
|
-
}, [paths, chainResult]);
|
|
42
|
-
return { ...readStateOf(chainResult), chain };
|
|
43
|
-
}
|
|
44
|
-
const EMPTY_PATHS = Object.freeze([]);
|
|
45
|
-
const EMPTY_CHAIN = Object.freeze([]);
|
|
46
|
-
function readStateOf(result) {
|
|
47
|
-
if (result === null)
|
|
48
|
-
return idleReadState();
|
|
7
|
+
export function useAncestors(_node) {
|
|
49
8
|
return {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
live: result.live,
|
|
53
|
-
seq: result.seq,
|
|
54
|
-
refetch: result.refetch,
|
|
9
|
+
...unsupportedReadState('navigation.ancestors requires an explicit parent Edge Class'),
|
|
10
|
+
chain: EMPTY_CHAIN,
|
|
55
11
|
};
|
|
56
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"location.hook.d.ts","sourceRoot":"","sources":["../../../src/navigation/hooks/location.hook.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKjD,8EAA8E;AAC9E,wBAAgB,WAAW,IAAI,WAAW,
|
|
1
|
+
{"version":3,"file":"location.hook.d.ts","sourceRoot":"","sources":["../../../src/navigation/hooks/location.hook.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKjD,8EAA8E;AAC9E,wBAAgB,WAAW,IAAI,WAAW,CAMzC"}
|
|
@@ -3,15 +3,13 @@
|
|
|
3
3
|
* path/node, missing flag). Throws outside any {@link NavScope}.
|
|
4
4
|
*/
|
|
5
5
|
import { useMemo } from 'react';
|
|
6
|
-
import { buildLocation
|
|
7
|
-
import { useHistoryVersion, useNavCtx
|
|
6
|
+
import { buildLocation } from '../location.js';
|
|
7
|
+
import { useGraphPoint, useHistoryVersion, useNavCtx } from '../scope.context.js';
|
|
8
8
|
/** The nearest scope's live location. Throws outside any {@link NavScope}. */
|
|
9
9
|
export function useLocation() {
|
|
10
10
|
const ctx = useNavCtx();
|
|
11
11
|
useHistoryVersion(ctx.history);
|
|
12
12
|
const entry = ctx.history.current;
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const settled = useSettled(result, shape);
|
|
16
|
-
return useMemo(() => buildLocation(entry, result, settled), [entry, result, settled]);
|
|
13
|
+
const result = useGraphPoint(entry?.node ?? null);
|
|
14
|
+
return useMemo(() => buildLocation(entry, result), [entry, result]);
|
|
17
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.hook.d.ts","sourceRoot":"","sources":["../../../src/navigation/hooks/scope.hook.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAMnD,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,IAAI,WAAW,CAAA;IACvB,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED,oFAAoF;AACpF,wBAAgB,WAAW,IAAI,cAAc,
|
|
1
|
+
{"version":3,"file":"scope.hook.d.ts","sourceRoot":"","sources":["../../../src/navigation/hooks/scope.hook.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAMnD,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,IAAI,WAAW,CAAA;IACvB,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED,oFAAoF;AACpF,wBAAgB,WAAW,IAAI,cAAc,CAQ5C"}
|
|
@@ -4,18 +4,16 @@
|
|
|
4
4
|
* scope.
|
|
5
5
|
*/
|
|
6
6
|
import { useCallback, useMemo } from 'react';
|
|
7
|
-
import { buildLocation
|
|
8
|
-
import {
|
|
7
|
+
import { buildLocation } from '../location.js';
|
|
8
|
+
import { useGraphPoint, useNavCtx } from '../scope.context.js';
|
|
9
9
|
import { useNavigateHandle } from './navigate.hook.js';
|
|
10
10
|
/** The nearest scope, for chrome/persistence (API §8.2). Throws outside a scope. */
|
|
11
11
|
export function useNavScope() {
|
|
12
12
|
const ctx = useNavCtx();
|
|
13
13
|
const navigate = useNavigateHandle(ctx);
|
|
14
14
|
const entry = ctx.history.current;
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const settled = useSettled(result, shape);
|
|
18
|
-
const location = useMemo(() => buildLocation(entry, result, settled), [entry, result, settled]);
|
|
15
|
+
const result = useGraphPoint(entry?.node ?? null);
|
|
16
|
+
const location = useMemo(() => buildLocation(entry, result), [entry, result]);
|
|
19
17
|
const snapshot = useCallback(() => ctx.history.snapshot(), [ctx.history]);
|
|
20
18
|
return { location, snapshot, navigate };
|
|
21
19
|
}
|
|
@@ -5,8 +5,10 @@ export { useNavigate } from './hooks/navigate.hook.js';
|
|
|
5
5
|
export { useAncestors } from './hooks/ancestors.hook.js';
|
|
6
6
|
export { useNavScope } from './hooks/scope.hook.js';
|
|
7
7
|
export type { NavScopeHandle } from './hooks/scope.hook.js';
|
|
8
|
-
export { Link } from './link.js';
|
|
9
|
-
export type { LinkProps } from './link.js';
|
|
8
|
+
export { Link, NodeLink, ViewLink } from './link.js';
|
|
9
|
+
export type { LinkProps, NodeLinkProps, ViewLinkProps } from './link.js';
|
|
10
|
+
export { NavigationScope, defineNavigation, enumParam, location, pathParam, useNavigation, } from './codec.js';
|
|
11
|
+
export type { LocationDefinition, NavigationDefinition, NavigationParam, NavigationParams, NavigationRoutes, NavigationTarget, } from './codec.js';
|
|
10
12
|
export { memoryAdapter } from './adapters/memory.adapter.js';
|
|
11
13
|
export { urlAdapter } from './adapters/url.adapter.js';
|
|
12
14
|
export type { NavAdapter } from './adapters/adapter.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/navigation/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/navigation/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpD,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACtD,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACnE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/navigation/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { useLocation } from './hooks/location.hook.js';
|
|
|
5
5
|
export { useNavigate } from './hooks/navigate.hook.js';
|
|
6
6
|
export { useAncestors } from './hooks/ancestors.hook.js';
|
|
7
7
|
export { useNavScope } from './hooks/scope.hook.js';
|
|
8
|
-
export { Link } from './link.js';
|
|
8
|
+
export { Link, NodeLink, ViewLink } from './link.js';
|
|
9
|
+
export { NavigationScope, defineNavigation, enumParam, location, pathParam, useNavigation, } from './codec.js';
|
|
9
10
|
export { memoryAdapter } from './adapters/memory.adapter.js';
|
|
10
11
|
export { urlAdapter } from './adapters/url.adapter.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnchorHTMLAttributes, ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { NavigationDefinition, NavigationTarget } from './codec.js';
|
|
2
3
|
import type { NavTarget } from './snapshot.js';
|
|
3
4
|
export interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
4
5
|
to: NavTarget;
|
|
@@ -8,4 +9,15 @@ export interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
|
8
9
|
children: ReactNode;
|
|
9
10
|
}
|
|
10
11
|
export declare function Link(props: LinkProps): ReactElement;
|
|
12
|
+
export type ViewLinkProps<Definition extends NavigationDefinition> = Omit<LinkProps, 'to'> & {
|
|
13
|
+
readonly navigation: Definition;
|
|
14
|
+
readonly to: NavigationTarget<Definition>;
|
|
15
|
+
};
|
|
16
|
+
/** Codec-admitted link for one declared View location. */
|
|
17
|
+
export declare function ViewLink<Definition extends NavigationDefinition>(props: ViewLinkProps<Definition>): ReactElement;
|
|
18
|
+
export type NodeLinkProps = Omit<LinkProps, 'to'> & {
|
|
19
|
+
readonly to: Extract<NavTarget, string | object>;
|
|
20
|
+
};
|
|
21
|
+
/** Canonical node-only link; use ViewLink when a View/params contract exists. */
|
|
22
|
+
export declare function NodeLink(props: NodeLinkProps): ReactElement;
|
|
11
23
|
//# sourceMappingURL=link.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/navigation/link.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAKpB,YAAY,EACZ,SAAS,EACV,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/navigation/link.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAKpB,YAAY,EACZ,SAAS,EACV,MAAM,OAAO,CAAA;AAWd,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAK9C,MAAM,WAAW,SAAU,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IACxE,EAAE,EAAE,SAAS,CAAA;IACb,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAA;IACtC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,YAAY,CA+EnD;AAED,MAAM,MAAM,aAAa,CAAC,UAAU,SAAS,oBAAoB,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG;IAC3F,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAA;CAC1C,CAAA;AAED,0DAA0D;AAC1D,wBAAgB,QAAQ,CAAC,UAAU,SAAS,oBAAoB,EAC9D,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,GAC/B,YAAY,CAGd;AAED,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG;IAClD,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;CACjD,CAAA;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAE3D"}
|
package/dist/navigation/link.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Query } from '@astrale-os/sdk/query';
|
|
2
3
|
/**
|
|
3
4
|
* Link (API §8.2) — navigates the nearest scope. Renders `<a href>` when the
|
|
4
5
|
* scope's adapter exposes a URL form (cmd/ctrl/middle-click then falls through
|
|
@@ -15,8 +16,9 @@ export function Link(props) {
|
|
|
15
16
|
const href = ctx.adapter.href?.(target);
|
|
16
17
|
const nodeRef = target.node;
|
|
17
18
|
const preload = useCallback(() => {
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
const query = Query.from({ kind: 'node', paths: [nodeRef] }).select({ kind: 'graph' });
|
|
20
|
+
void ctx.store.preload(query, { page: { size: 1 } }).catch(() => { });
|
|
21
|
+
}, [ctx.store, nodeRef]);
|
|
20
22
|
useEffect(() => {
|
|
21
23
|
if (prefetch === 'render')
|
|
22
24
|
preload();
|
|
@@ -60,3 +62,12 @@ export function Link(props) {
|
|
|
60
62
|
const linkRole = href !== undefined ? { href } : { role: 'link', tabIndex: rest.tabIndex ?? 0 };
|
|
61
63
|
return (_jsx("a", { ...rest, ...linkRole, onClick: handleClick, onKeyDown: handleKeyDown, onPointerEnter: handlePointerEnter, onPointerDown: handlePointerDown, onFocus: handleFocus, children: children }));
|
|
62
64
|
}
|
|
65
|
+
/** Codec-admitted link for one declared View location. */
|
|
66
|
+
export function ViewLink(props) {
|
|
67
|
+
const { navigation, to, ...link } = props;
|
|
68
|
+
return _jsx(Link, { ...link, to: navigation.encode(to) });
|
|
69
|
+
}
|
|
70
|
+
/** Canonical node-only link; use ViewLink when a View/params contract exists. */
|
|
71
|
+
export function NodeLink(props) {
|
|
72
|
+
return _jsx(Link, { ...props });
|
|
73
|
+
}
|