@astrale-os/shell-react 0.2.9 → 0.2.10-beta.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/dist/application/apps/app-host.d.ts +4 -15
- package/dist/application/apps/app-host.d.ts.map +1 -1
- package/dist/application/apps/app-host.js +1 -1
- 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/astrale.d.ts +14 -0
- package/dist/components/astrale.d.ts.map +1 -0
- package/dist/components/astrale.js +12 -0
- 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 +6 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +3 -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 +9 -11
- package/dist/window/host.d.ts.map +1 -1
- package/dist/window/host.js +26 -62
- 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 +2 -2
- 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/package.json +20 -8
- package/src/application/apps/app-host.tsx +11 -15
- 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/astrale.tsx +40 -0
- package/src/components/boundaries.tsx +113 -0
- package/src/components/can.tsx +16 -0
- package/src/components/index.ts +13 -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 +131 -124
- 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 +35 -77
- package/src/window/hub.ts +33 -0
- package/src/window/index.ts +3 -3
- package/src/window/lifecycle/mount.ts +15 -160
- package/src/window/lifecycle/states.ts +1 -5
- 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,48 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Node, NodeId } from '@astrale-os/sdk/graph/node';
|
|
2
|
+
import type { NodePath } from '@astrale-os/sdk/graph/path';
|
|
3
|
+
import type { Key } from '@astrale-os/sdk/schema';
|
|
4
|
+
import type { ReadState } from '../graph/memory/read/envelope.js';
|
|
2
5
|
import type { SerializedLocation } from './history.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
export type Node = NonNullable<LiveResult['node']>;
|
|
9
|
-
export type NodeId = Node['id'];
|
|
10
|
-
/** The live, id-anchored location a scope currently points at (API §8.1). */
|
|
6
|
+
export interface PointResult extends ReadState {
|
|
7
|
+
readonly node: Node | null;
|
|
8
|
+
}
|
|
9
|
+
/** One canonical location and its current caller-visible point projection. */
|
|
11
10
|
export interface NavLocation {
|
|
12
|
-
|
|
13
|
-
readonly id: NodeId;
|
|
14
|
-
/** LIVE projection of the node's current path (empty until first resolve). */
|
|
15
|
-
readonly path: string;
|
|
16
|
-
/** Live memory node — null while cold, or after the anchor stops resolving. */
|
|
11
|
+
readonly target: NodePath | null;
|
|
12
|
+
readonly id: NodeId | null;
|
|
17
13
|
readonly node: Node | null;
|
|
18
|
-
|
|
19
|
-
readonly view?: string;
|
|
14
|
+
readonly view?: Key.View;
|
|
20
15
|
readonly params: Readonly<Record<string, string>>;
|
|
21
|
-
/** The anchor no longer resolves (deleted / masked). */
|
|
22
16
|
readonly missing: boolean;
|
|
23
17
|
}
|
|
24
|
-
/** The idle location a scope with no current entry projects (inert / boot). */
|
|
25
18
|
export declare const IDLE_LOCATION: NavLocation;
|
|
26
|
-
|
|
27
|
-
export
|
|
28
|
-
/**
|
|
29
|
-
* Whether a read has definitively settled — data present, a hard error, or a
|
|
30
|
-
* completed empty fetch. Guards `missing` (and the missing policy) against the
|
|
31
|
-
* one-render false-empty before a cold shape's first fetch is even in flight.
|
|
32
|
-
*/
|
|
33
|
-
export declare function useSettled(result: LiveResult | null, key: string | null): boolean;
|
|
34
|
-
/** The raw path of a live node (empty when cold). */
|
|
35
|
-
export declare function pathOf(node: Node | null): string;
|
|
36
|
-
/** Best-effort anchor id from a stored ref (`@<id>` → id, else the raw ref). */
|
|
37
|
-
export declare function idHint(ref: string): string;
|
|
38
|
-
/** Best-effort path from a stored ref (a `/…` ref is already a path). */
|
|
39
|
-
export declare function pathHint(ref: string): string;
|
|
40
|
-
/** The parent absolute path, or null at (or above) root. */
|
|
41
|
-
export declare function parentPath(raw: string): string | null;
|
|
42
|
-
/**
|
|
43
|
-
* The inclusive, root-first path chain for an absolute path — the ancestry the
|
|
44
|
-
* kernel tree encodes in the slug path (`/a/b/c` → `/`, `/a`, `/a/b`, `/a/b/c`).
|
|
45
|
-
* The node itself is the last element, so breadcrumbs map the chain directly.
|
|
46
|
-
*/
|
|
47
|
-
export declare function chainPaths(raw: string): string[];
|
|
19
|
+
export declare function buildLocation(entry: SerializedLocation | null, result: PointResult | null): NavLocation;
|
|
20
|
+
export type { Node, NodeId };
|
|
48
21
|
//# sourceMappingURL=location.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../src/navigation/location.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../src/navigation/location.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAA;AAIjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEtD,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;CAC3B;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAID,eAAO,MAAM,aAAa,EAAE,WAM1B,CAAA;AAEF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,kBAAkB,GAAG,IAAI,EAChC,MAAM,EAAE,WAAW,GAAG,IAAI,GACzB,WAAW,CAWb;AAOD,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA"}
|
|
@@ -1,88 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
/**
|
|
3
|
-
* NavLocation projection (API §8.1) — the live, id-anchored location a scope
|
|
4
|
-
* points at (live path, missing flag), its `buildLocation` assembly, the
|
|
5
|
-
* `useSettled` guard against a one-render false-empty, and the framework-free
|
|
6
|
-
* path math (parent/chain) the scope and hooks share.
|
|
7
|
-
*/
|
|
8
|
-
import { useEffect, useRef } from 'react';
|
|
1
|
+
import { Path } from '@astrale-os/sdk/graph/path';
|
|
9
2
|
const EMPTY_PARAMS = Object.freeze({});
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
id:
|
|
13
|
-
path: '',
|
|
3
|
+
export const IDLE_LOCATION = Object.freeze({
|
|
4
|
+
target: null,
|
|
5
|
+
id: null,
|
|
14
6
|
node: null,
|
|
15
7
|
params: EMPTY_PARAMS,
|
|
16
8
|
missing: false,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export function buildLocation(entry, result, settled) {
|
|
9
|
+
});
|
|
10
|
+
export function buildLocation(entry, result) {
|
|
20
11
|
if (entry === null)
|
|
21
12
|
return IDLE_LOCATION;
|
|
22
13
|
const node = result?.node ?? null;
|
|
23
14
|
return {
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
target: entry.node,
|
|
16
|
+
id: node?.id ?? idAnchor(entry.node),
|
|
26
17
|
node,
|
|
27
|
-
...(entry.view
|
|
28
|
-
params: entry.params ??
|
|
29
|
-
missing:
|
|
18
|
+
...(entry.view === undefined ? {} : { view: entry.view }),
|
|
19
|
+
params: entry.params ?? EMPTY_PARAMS,
|
|
20
|
+
missing: result !== null && !result.pending && node === null,
|
|
30
21
|
};
|
|
31
22
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* one-render false-empty before a cold shape's first fetch is even in flight.
|
|
36
|
-
*/
|
|
37
|
-
export function useSettled(result, key) {
|
|
38
|
-
const sawPending = useRef(new Map());
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (key !== null && result?.pending === true)
|
|
41
|
-
sawPending.current.set(key, true);
|
|
42
|
-
}, [key, result?.pending]);
|
|
43
|
-
if (key === null || result === null)
|
|
44
|
-
return false;
|
|
45
|
-
if (result.node !== null)
|
|
46
|
-
return true;
|
|
47
|
-
if (result.error !== undefined)
|
|
48
|
-
return true;
|
|
49
|
-
return !result.pending && sawPending.current.get(key) === true;
|
|
50
|
-
}
|
|
51
|
-
// ── path math ──────────────────────────────────────────────────────────────
|
|
52
|
-
/** The raw path of a live node (empty when cold). */
|
|
53
|
-
export function pathOf(node) {
|
|
54
|
-
return node ? rawOf(node.path) : '';
|
|
55
|
-
}
|
|
56
|
-
/** Best-effort anchor id from a stored ref (`@<id>` → id, else the raw ref). */
|
|
57
|
-
export function idHint(ref) {
|
|
58
|
-
return ref.startsWith('@') ? ref.slice(1) : ref;
|
|
59
|
-
}
|
|
60
|
-
/** Best-effort path from a stored ref (a `/…` ref is already a path). */
|
|
61
|
-
export function pathHint(ref) {
|
|
62
|
-
return ref.startsWith('/') ? ref : '';
|
|
63
|
-
}
|
|
64
|
-
/** The parent absolute path, or null at (or above) root. */
|
|
65
|
-
export function parentPath(raw) {
|
|
66
|
-
const norm = raw.replace(/\/+$/, '');
|
|
67
|
-
if (norm === '' || norm === '/')
|
|
68
|
-
return null;
|
|
69
|
-
const idx = norm.lastIndexOf('/');
|
|
70
|
-
return idx <= 0 ? '/' : norm.slice(0, idx);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* The inclusive, root-first path chain for an absolute path — the ancestry the
|
|
74
|
-
* kernel tree encodes in the slug path (`/a/b/c` → `/`, `/a`, `/a/b`, `/a/b/c`).
|
|
75
|
-
* The node itself is the last element, so breadcrumbs map the chain directly.
|
|
76
|
-
*/
|
|
77
|
-
export function chainPaths(raw) {
|
|
78
|
-
const norm = raw.replace(/\/+$/, '');
|
|
79
|
-
if (norm === '' || norm === '/')
|
|
80
|
-
return ['/'];
|
|
81
|
-
const out = ['/'];
|
|
82
|
-
let acc = '';
|
|
83
|
-
for (const seg of norm.split('/').filter(Boolean)) {
|
|
84
|
-
acc += `/${seg}`;
|
|
85
|
-
out.push(acc);
|
|
86
|
-
}
|
|
87
|
-
return out;
|
|
23
|
+
function idAnchor(target) {
|
|
24
|
+
const path = Path.from(target);
|
|
25
|
+
return path.ast.anchor.kind === 'id' && path.ast.steps.length === 0 ? path.ast.anchor.id : null;
|
|
88
26
|
}
|
|
@@ -1,64 +1,55 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { GraphStore } from '@astrale-os/kernel-client/store';
|
|
2
2
|
import type { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import { NodePath } from '@astrale-os/sdk/graph/path';
|
|
3
4
|
import type { NavAdapter } from './adapters/adapter.js';
|
|
4
|
-
import type { NavSnapshot } from './history.js';
|
|
5
|
-
import type { NavLocation } from './location.js';
|
|
5
|
+
import type { NavSnapshot, SerializedLocation } from './history.js';
|
|
6
|
+
import type { NavLocation, PointResult } from './location.js';
|
|
6
7
|
import type { NavTarget } from './snapshot.js';
|
|
7
8
|
import { NavHistory } from './history.js';
|
|
8
|
-
/** The imperative navigation surface (API §8.2). */
|
|
9
9
|
export interface Navigate {
|
|
10
10
|
(to: NavTarget, opts?: {
|
|
11
11
|
replace?: boolean;
|
|
12
12
|
}): void;
|
|
13
13
|
back(): void;
|
|
14
14
|
forward(): void;
|
|
15
|
-
/**
|
|
16
|
-
up():
|
|
15
|
+
/** Unsupported until the caller supplies an explicit parent Edge Class. */
|
|
16
|
+
up(): never;
|
|
17
17
|
readonly canBack: boolean;
|
|
18
18
|
readonly canForward: boolean;
|
|
19
19
|
}
|
|
20
|
-
/** A mutable `Navigate` — the scope stamps `canBack`/`canForward` onto it live. */
|
|
21
20
|
export interface MutableNavigate {
|
|
22
21
|
(to: Parameters<Navigate>[0], opts?: Parameters<Navigate>[1]): void;
|
|
23
22
|
back(): void;
|
|
24
23
|
forward(): void;
|
|
25
|
-
up():
|
|
24
|
+
up(): never;
|
|
26
25
|
canBack: boolean;
|
|
27
26
|
canForward: boolean;
|
|
28
27
|
}
|
|
29
|
-
/** The nearest scope's shared handle (stable for the scope's lifetime). */
|
|
30
28
|
export interface NavCtx {
|
|
31
29
|
readonly history: NavHistory;
|
|
32
|
-
readonly
|
|
30
|
+
readonly store: GraphStore;
|
|
33
31
|
readonly adapter: NavAdapter;
|
|
34
32
|
readonly navigate: MutableNavigate;
|
|
35
33
|
}
|
|
36
34
|
export declare const NavContext: import("react").Context<NavCtx | null>;
|
|
37
|
-
/** The nearest scope, or throw — the door every public nav hook goes through. */
|
|
38
35
|
export declare function useNavCtx(): NavCtx;
|
|
39
|
-
/** The nearest scope or null (for `useAncestors`, usable outside a scope). */
|
|
40
36
|
export declare function useOptionalNavCtx(): NavCtx | null;
|
|
41
|
-
/** Re-render on any history change (no-op subscription when there is no scope). */
|
|
42
37
|
export declare function useHistoryVersion(history: NavHistory | null): number;
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
export declare function useMemoryShape(memory: GraphMemory, shape: ShapeInput | null): LiveResult | null;
|
|
48
|
-
/** The missing-anchor policy — a fallback strategy or a caller-supplied resolver. */
|
|
49
|
-
export type MissingPolicy = 'ancestor' | 'hold' | ((loc: NavLocation) => NavTarget | null);
|
|
38
|
+
/** Caller-scoped canonical point read through the provider's one GraphStore. */
|
|
39
|
+
export declare function useGraphPoint(target: NodePath | null): PointResult | null;
|
|
40
|
+
type MissingResolver = (location: NavLocation) => NavTarget | null;
|
|
41
|
+
export type MissingPolicy = 'hold' | MissingResolver;
|
|
50
42
|
export interface NavScopeProps {
|
|
51
|
-
/** Persistence seam. Default: a fresh {@link memoryAdapter} (captured once). */
|
|
52
43
|
adapter?: NavAdapter;
|
|
53
|
-
/** A saved snapshot — revalidated against the memory; dead entries dropped. */
|
|
54
44
|
restore?: NavSnapshot;
|
|
55
|
-
/** Seed target when neither `adapter.read()` nor `restore` yields one. */
|
|
56
45
|
initial?: NavTarget;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/** What to do when the current anchor stops resolving. Default `'ancestor'`. */
|
|
46
|
+
onChange?: (location: NavLocation, snapshot: NavSnapshot) => void;
|
|
47
|
+
/** Default `hold`; parent fallback requires an explicit caller relationship. */
|
|
60
48
|
missing?: MissingPolicy;
|
|
49
|
+
/** Closed codec admission applied before any history or adapter mutation. */
|
|
50
|
+
admit?: (location: SerializedLocation) => SerializedLocation | null;
|
|
61
51
|
children: ReactNode;
|
|
62
52
|
}
|
|
63
53
|
export declare function NavScope(props: NavScopeProps): ReactElement;
|
|
54
|
+
export {};
|
|
64
55
|
//# sourceMappingURL=scope.context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.context.d.ts","sourceRoot":"","sources":["../../src/navigation/scope.context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"scope.context.d.ts","sourceRoot":"","sources":["../../src/navigation/scope.context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAsB,MAAM,iCAAiC,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAcrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAO9C,OAAO,EAAE,UAAU,EAAe,MAAM,cAAc,CAAA;AAItD,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IACnD,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,2EAA2E;IAC3E,EAAE,IAAI,KAAK,CAAA;IACX,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IACnE,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,EAAE,IAAI,KAAK,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;CACnC;AAED,eAAO,MAAM,UAAU,wCAAqC,CAAA;AAG5D,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD;AAID,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM,CAOpE;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,CA6BzE;AAED,KAAK,eAAe,GAAG,CAAC,QAAQ,EAAE,WAAW,KAAK,SAAS,GAAG,IAAI,CAAA;AAClE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,eAAe,CAAA;AAEpD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAA;IACjE,gFAAgF;IAChF,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,kBAAkB,GAAG,IAAI,CAAA;IACnE,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAsH3D"}
|
|
@@ -1,178 +1,210 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* stack against the memory, mirrors navigations to/from the adapter, and runs the
|
|
6
|
-
* `missing` policy when the current anchor stops resolving. Also the scope's shared
|
|
7
|
-
* glue (`NavContext`, the `useSyncExternalStore` reads) and the imperative
|
|
8
|
-
* `Navigate` surface. Scopes nest.
|
|
9
|
-
*/
|
|
2
|
+
import { NodePath } from '@astrale-os/sdk/graph/path';
|
|
3
|
+
import { Query } from '@astrale-os/sdk/query';
|
|
4
|
+
import { Key } from '@astrale-os/sdk/schema';
|
|
10
5
|
import { createContext, startTransition, useCallback, useContext, useEffect, useMemo, useRef, useSyncExternalStore, } from 'react';
|
|
11
|
-
import {
|
|
6
|
+
import { UnsupportedFeatureError } from '../graph/memory/read/envelope.js';
|
|
7
|
+
import { useStoreResource } from '../graph/resource.js';
|
|
8
|
+
import { useGraphStore } from '../graph/store.js';
|
|
9
|
+
import { useShell } from '../session/shell.hook.js';
|
|
12
10
|
import { memoryAdapter } from './adapters/memory.adapter.js';
|
|
13
11
|
import { NavHistory, seedEntries } from './history.js';
|
|
14
|
-
import { buildLocation
|
|
12
|
+
import { buildLocation } from './location.js';
|
|
15
13
|
import { revalidateAndPrune, serializeTarget } from './snapshot.js';
|
|
16
14
|
export const NavContext = createContext(null);
|
|
17
15
|
NavContext.displayName = 'AstraleNavContext';
|
|
18
|
-
/** The nearest scope, or throw — the door every public nav hook goes through. */
|
|
19
16
|
export function useNavCtx() {
|
|
20
17
|
const ctx = useContext(NavContext);
|
|
21
18
|
if (ctx === null)
|
|
22
19
|
throw new Error('nav hooks must be used within a <NavScope>');
|
|
23
20
|
return ctx;
|
|
24
21
|
}
|
|
25
|
-
/** The nearest scope or null (for `useAncestors`, usable outside a scope). */
|
|
26
22
|
export function useOptionalNavCtx() {
|
|
27
23
|
return useContext(NavContext);
|
|
28
24
|
}
|
|
29
25
|
const NOOP_UNSUB = () => undefined;
|
|
30
|
-
/** Re-render on any history change (no-op subscription when there is no scope). */
|
|
31
26
|
export function useHistoryVersion(history) {
|
|
32
|
-
const subscribe = useCallback((
|
|
33
|
-
const getSnapshot = useCallback(() => (history
|
|
27
|
+
const subscribe = useCallback((listener) => (history === null ? NOOP_UNSUB : history.subscribe(listener)), [history]);
|
|
28
|
+
const getSnapshot = useCallback(() => (history === null ? 0 : history.getVersion()), [history]);
|
|
34
29
|
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
35
30
|
}
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
31
|
+
/** Caller-scoped canonical point read through the provider's one GraphStore. */
|
|
32
|
+
export function useGraphPoint(target) {
|
|
33
|
+
const query = useMemo(() => target === null
|
|
34
|
+
? null
|
|
35
|
+
: Query.from({ kind: 'node', paths: [target], binding: 'navigation_target' }).select({
|
|
36
|
+
kind: 'graph',
|
|
37
|
+
}), [target]);
|
|
38
|
+
const project = useCallback((response) => {
|
|
39
|
+
const result = response.result;
|
|
40
|
+
if (result.kind !== 'graph' || result.selection.kind !== 'node')
|
|
41
|
+
return null;
|
|
42
|
+
const id = result.selection.ids[0];
|
|
43
|
+
return id === undefined ? null : (result.graph.nodes.find((node) => node.id === id) ?? null);
|
|
44
|
+
}, [query]);
|
|
45
|
+
const resource = useStoreResource(query, 1, project);
|
|
46
|
+
if (target === null)
|
|
47
|
+
return null;
|
|
48
|
+
return {
|
|
49
|
+
node: resource.data ?? null,
|
|
50
|
+
pending: resource.state === 'loading' || resource.state === 'refreshing',
|
|
51
|
+
error: resource.error,
|
|
52
|
+
live: false,
|
|
53
|
+
seq: 0,
|
|
54
|
+
refetch: resource.refresh,
|
|
55
|
+
};
|
|
44
56
|
}
|
|
45
57
|
export function NavScope(props) {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
// (or a re-passed `initial`) must never rebuild the scope's state.
|
|
58
|
+
const store = useGraphStore();
|
|
59
|
+
const shell = useShell();
|
|
49
60
|
const adapterRef = useRef(null);
|
|
50
61
|
if (adapterRef.current === null)
|
|
51
62
|
adapterRef.current = props.adapter ?? memoryAdapter();
|
|
52
63
|
const adapter = adapterRef.current;
|
|
64
|
+
if (adapter.kind === 'browser' && shell.hostCapabilities.navigation.history !== 'browser') {
|
|
65
|
+
throw new Error('Browser navigation is not granted to this Shell.');
|
|
66
|
+
}
|
|
67
|
+
const admitRef = useRef(props.admit);
|
|
68
|
+
admitRef.current = props.admit;
|
|
69
|
+
const admit = (location) => {
|
|
70
|
+
if (location === null)
|
|
71
|
+
return null;
|
|
72
|
+
const portable = admitLocation(location);
|
|
73
|
+
return admitRef.current?.(portable) ?? portable;
|
|
74
|
+
};
|
|
53
75
|
const historyRef = useRef(null);
|
|
54
76
|
if (historyRef.current === null) {
|
|
55
|
-
const seed = seedEntries(adapter.read(), props.restore
|
|
77
|
+
const seed = seedEntries(admit(adapter.read()), props.restore === undefined || props.restore.v !== 1
|
|
78
|
+
? undefined
|
|
79
|
+
: {
|
|
80
|
+
entries: props.restore.entries.flatMap((entry) => {
|
|
81
|
+
const accepted = admit(entry);
|
|
82
|
+
return accepted === null ? [] : [accepted];
|
|
83
|
+
}),
|
|
84
|
+
cursor: props.restore.cursor,
|
|
85
|
+
}, props.initial === undefined ? null : admit(serializeTarget(props.initial)));
|
|
56
86
|
historyRef.current = new NavHistory(seed.entries, seed.cursor);
|
|
57
87
|
}
|
|
58
88
|
const history = historyRef.current;
|
|
59
|
-
// Latest-value refs so the stable navigate + effects read current inputs.
|
|
60
|
-
const memoryRef = useRef(memory);
|
|
61
|
-
memoryRef.current = memory;
|
|
62
89
|
const onChangeRef = useRef(props.onChange);
|
|
63
90
|
onChangeRef.current = props.onChange;
|
|
64
91
|
const missingRef = useRef(props.missing);
|
|
65
92
|
missingRef.current = props.missing;
|
|
93
|
+
const historyVersion = useHistoryVersion(history);
|
|
66
94
|
const fireOnChange = useCallback(() => {
|
|
67
|
-
|
|
68
|
-
if (cb === undefined)
|
|
69
|
-
return;
|
|
70
|
-
const entry = history.current;
|
|
71
|
-
const live = entry !== null ? memoryRef.current.peek(entry.node) : null;
|
|
72
|
-
cb(buildLocation(entry, live, (live?.node ?? null) !== null), history.snapshot());
|
|
95
|
+
onChangeRef.current?.(buildLocation(history.current, null), history.snapshot());
|
|
73
96
|
}, [history]);
|
|
74
|
-
// The one stable navigate object; hooks re-stamp canBack/canForward onto it.
|
|
75
97
|
const navigate = useMemo(() => {
|
|
76
98
|
const commit = (changed, replace) => {
|
|
77
99
|
if (!changed)
|
|
78
100
|
return;
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
adapter.write(
|
|
101
|
+
const location = history.current;
|
|
102
|
+
if (location !== null)
|
|
103
|
+
adapter.write(location, { replace });
|
|
82
104
|
fireOnChange();
|
|
83
105
|
};
|
|
84
|
-
const nav = ((to,
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
106
|
+
const nav = ((to, options) => {
|
|
107
|
+
const replace = options?.replace ?? false;
|
|
108
|
+
const location = admit(serializeTarget(to));
|
|
109
|
+
if (location === null)
|
|
110
|
+
throw new TypeError('Navigation target was rejected by its codec.');
|
|
111
|
+
startTransition(() => commit(history.push(location, replace), replace));
|
|
88
112
|
});
|
|
89
113
|
nav.back = () => startTransition(() => commit(history.back(), false));
|
|
90
114
|
nav.forward = () => startTransition(() => commit(history.forward(), false));
|
|
91
115
|
nav.up = () => {
|
|
92
|
-
|
|
93
|
-
if (entry === null)
|
|
94
|
-
return;
|
|
95
|
-
const live = memoryRef.current.peek(entry.node);
|
|
96
|
-
const raw = live?.node ? pathOf(live.node) : pathHint(entry.node);
|
|
97
|
-
const parent = raw !== '' ? parentPath(raw) : null;
|
|
98
|
-
if (parent !== null)
|
|
99
|
-
nav(parent);
|
|
116
|
+
throw new UnsupportedFeatureError('navigation.up requires an explicit parent Edge Class');
|
|
100
117
|
};
|
|
101
118
|
nav.canBack = history.canBack;
|
|
102
119
|
nav.canForward = history.canForward;
|
|
103
120
|
return nav;
|
|
104
|
-
}, [history, adapter, fireOnChange]);
|
|
105
|
-
// Re-render the scope on every navigation so the missing watcher tracks the
|
|
106
|
-
// current entry (consumers re-render through their own version subscription).
|
|
107
|
-
const historyVersion = useHistoryVersion(history);
|
|
108
|
-
// Mount: canonicalize a non-adapter seed into the adapter, then relay external
|
|
109
|
-
// (browser/URL) changes back into the history.
|
|
121
|
+
}, [history, adapter, fireOnChange, historyVersion]);
|
|
110
122
|
useEffect(() => {
|
|
111
|
-
const
|
|
112
|
-
if (
|
|
113
|
-
adapter.write(
|
|
123
|
+
const seed = history.current;
|
|
124
|
+
if (seed !== null && adapter.read() === null)
|
|
125
|
+
adapter.write(seed, { replace: true });
|
|
114
126
|
return adapter.subscribe(() => {
|
|
115
|
-
const
|
|
116
|
-
if (
|
|
127
|
+
const location = admit(adapter.read());
|
|
128
|
+
if (location === null)
|
|
117
129
|
return;
|
|
118
130
|
startTransition(() => {
|
|
119
|
-
if (history.syncExternal(
|
|
131
|
+
if (history.syncExternal(location))
|
|
120
132
|
fireOnChange();
|
|
121
133
|
});
|
|
122
134
|
});
|
|
123
135
|
}, [history, adapter, fireOnChange]);
|
|
124
|
-
// Restore revalidation — once, against the shared memory.
|
|
125
|
-
const revalidatedRef = useRef(false);
|
|
126
136
|
useEffect(() => {
|
|
127
|
-
if (
|
|
137
|
+
if (props.restore === undefined)
|
|
128
138
|
return;
|
|
129
|
-
|
|
130
|
-
void revalidateAndPrune(history,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
let current = true;
|
|
140
|
+
void revalidateAndPrune(history, store, shell).then((changed) => {
|
|
141
|
+
if (!current || !changed)
|
|
142
|
+
return;
|
|
143
|
+
const accepted = history.current;
|
|
144
|
+
if (accepted === null)
|
|
145
|
+
adapter.clear({ replace: true });
|
|
146
|
+
else
|
|
147
|
+
adapter.write(accepted, { replace: true });
|
|
148
|
+
fireOnChange();
|
|
149
|
+
});
|
|
150
|
+
return () => {
|
|
151
|
+
current = false;
|
|
152
|
+
};
|
|
153
|
+
}, [store, shell, history, adapter, props.restore, fireOnChange]);
|
|
154
|
+
const current = history.current;
|
|
155
|
+
const result = useGraphPoint(current?.node ?? null);
|
|
156
|
+
const handled = useRef(null);
|
|
143
157
|
useEffect(() => {
|
|
144
|
-
|
|
145
|
-
if (entry === null)
|
|
158
|
+
if (current === null || result === null || result.pending)
|
|
146
159
|
return;
|
|
147
|
-
if (
|
|
148
|
-
|
|
160
|
+
if (result.node !== null) {
|
|
161
|
+
handled.current = null;
|
|
149
162
|
return;
|
|
150
163
|
}
|
|
151
|
-
if (
|
|
164
|
+
if (handled.current === current.node)
|
|
152
165
|
return;
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}, [
|
|
161
|
-
const ctx = useMemo(() => ({ history,
|
|
166
|
+
handled.current = current.node;
|
|
167
|
+
const policy = missingRef.current ?? 'hold';
|
|
168
|
+
if (typeof policy === 'function') {
|
|
169
|
+
const target = policy(buildLocation(current, result));
|
|
170
|
+
if (target !== null)
|
|
171
|
+
navigate(target, { replace: true });
|
|
172
|
+
}
|
|
173
|
+
}, [current, result, navigate, historyVersion]);
|
|
174
|
+
const ctx = useMemo(() => ({ history, store, adapter, navigate }), [history, store, adapter, navigate]);
|
|
162
175
|
return _jsx(NavContext.Provider, { value: ctx, children: props.children });
|
|
163
176
|
}
|
|
164
|
-
function
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
function admitLocation(location) {
|
|
178
|
+
if (location === null || typeof location !== 'object' || Array.isArray(location)) {
|
|
179
|
+
throw new TypeError('Navigation location is invalid.');
|
|
180
|
+
}
|
|
181
|
+
const node = NodePath(location.node);
|
|
182
|
+
let view;
|
|
183
|
+
if (location.view !== undefined) {
|
|
184
|
+
const key = Key(location.view);
|
|
185
|
+
if (!Key.ref(key).startsWith('view.'))
|
|
186
|
+
throw new TypeError('Navigation View key is invalid.');
|
|
187
|
+
view = key;
|
|
188
|
+
}
|
|
189
|
+
const params = {};
|
|
190
|
+
if (location.params !== undefined) {
|
|
191
|
+
if (location.params === null ||
|
|
192
|
+
typeof location.params !== 'object' ||
|
|
193
|
+
Array.isArray(location.params)) {
|
|
194
|
+
throw new TypeError('Navigation params are invalid.');
|
|
195
|
+
}
|
|
196
|
+
for (const [key, value] of Object.entries(location.params)) {
|
|
197
|
+
if (/token|credential|authorization|secret/i.test(key)) {
|
|
198
|
+
throw new TypeError(`Navigation param '${key}' is sensitive.`);
|
|
199
|
+
}
|
|
200
|
+
if (typeof value !== 'string')
|
|
201
|
+
throw new TypeError(`Navigation param '${key}' is invalid.`);
|
|
202
|
+
params[key] = value;
|
|
203
|
+
}
|
|
172
204
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
205
|
+
return Object.freeze({
|
|
206
|
+
node,
|
|
207
|
+
...(view === undefined ? {} : { view }),
|
|
208
|
+
...(Object.keys(params).length === 0 ? {} : { params: Object.freeze(params) }),
|
|
209
|
+
});
|
|
178
210
|
}
|
|
@@ -1,22 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
7
|
-
/**
|
|
8
|
-
export type NavTarget =
|
|
9
|
-
node:
|
|
10
|
-
view?:
|
|
11
|
-
params?: Record<string, string>;
|
|
1
|
+
import type { GraphStore } from '@astrale-os/kernel-client/store';
|
|
2
|
+
import type { Node } from '@astrale-os/sdk/graph/node';
|
|
3
|
+
import type { PathLike } from '@astrale-os/sdk/graph/path';
|
|
4
|
+
import type { Key } from '@astrale-os/sdk/schema';
|
|
5
|
+
import type { Shell } from '@astrale-os/shell';
|
|
6
|
+
import type { NavHistory, SerializedLocation } from './history.js';
|
|
7
|
+
/** Canonical navigation inputs; there is no implicit slash-tree or bare-id grammar. */
|
|
8
|
+
export type NavTarget = PathLike | Node | {
|
|
9
|
+
readonly node: PathLike | Node;
|
|
10
|
+
readonly view?: Key.View;
|
|
11
|
+
readonly params?: Record<string, string>;
|
|
12
12
|
};
|
|
13
|
-
/** Normalize
|
|
13
|
+
/** Normalize every target to canonical astrale-node-path-v1 text. */
|
|
14
14
|
export declare function serializeTarget(target: NavTarget): SerializedLocation;
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
* Each entry is point-read one-shot; a null/failed read is a dead anchor. The
|
|
18
|
-
* cursor re-lands on the surviving current entry, else the nearest survivor
|
|
19
|
-
* before it.
|
|
20
|
-
*/
|
|
21
|
-
export declare function revalidateAndPrune(history: NavHistory, memory: GraphMemory): Promise<void>;
|
|
15
|
+
/** Drop restored entries that no longer resolve under the authenticated Graph capability. */
|
|
16
|
+
export declare function revalidateAndPrune(history: NavHistory, store: GraphStore, shell: Shell): Promise<boolean>;
|
|
22
17
|
//# sourceMappingURL=snapshot.d.ts.map
|