@astrale-os/shell-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/dist/application/apps/app-host.d.ts +31 -0
- package/dist/application/apps/app-host.d.ts.map +1 -0
- package/dist/application/apps/app-host.js +59 -0
- package/dist/application/apps/app-logo.d.ts +19 -0
- package/dist/application/apps/app-logo.d.ts.map +1 -0
- package/dist/application/apps/app-logo.js +31 -0
- package/dist/application/apps/apps.hook.d.ts +12 -0
- package/dist/application/apps/apps.hook.d.ts.map +1 -0
- package/dist/application/apps/apps.hook.js +51 -0
- package/dist/application/apps/open-app.hook.d.ts +10 -0
- package/dist/application/apps/open-app.hook.d.ts.map +1 -0
- package/dist/application/apps/open-app.hook.js +7 -0
- package/dist/application/index.d.ts +18 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +12 -0
- package/dist/application/roles.hook.d.ts +7 -0
- package/dist/application/roles.hook.d.ts.map +1 -0
- package/dist/application/roles.hook.js +23 -0
- package/dist/application/spaces/current-space.hook.d.ts +7 -0
- package/dist/application/spaces/current-space.hook.d.ts.map +1 -0
- package/dist/application/spaces/current-space.hook.js +27 -0
- package/dist/application/spaces/current-space.store.d.ts +32 -0
- package/dist/application/spaces/current-space.store.d.ts.map +1 -0
- package/dist/application/spaces/current-space.store.js +79 -0
- package/dist/application/spaces/space.hook.d.ts +5 -0
- package/dist/application/spaces/space.hook.d.ts.map +1 -0
- package/dist/application/spaces/space.hook.js +25 -0
- package/dist/application/spaces/spaces.hook.d.ts +14 -0
- package/dist/application/spaces/spaces.hook.d.ts.map +1 -0
- package/dist/application/spaces/spaces.hook.js +82 -0
- package/dist/application/user/user.hook.d.ts +10 -0
- package/dist/application/user/user.hook.d.ts.map +1 -0
- package/dist/application/user/user.hook.js +19 -0
- package/dist/application/user/user.store.d.ts +35 -0
- package/dist/application/user/user.store.d.ts.map +1 -0
- package/dist/application/user/user.store.js +51 -0
- package/dist/auth/act-as.context.d.ts +40 -0
- package/dist/auth/act-as.context.d.ts.map +1 -0
- package/dist/auth/act-as.context.js +84 -0
- package/dist/auth/auth.hook.d.ts +3 -0
- package/dist/auth/auth.hook.d.ts.map +1 -0
- package/dist/auth/auth.hook.js +25 -0
- package/dist/auth/can.hook.d.ts +40 -0
- package/dist/auth/can.hook.d.ts.map +1 -0
- package/dist/auth/can.hook.js +119 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/self.hook.d.ts +3 -0
- package/dist/auth/self.hook.d.ts.map +1 -0
- package/dist/auth/self.hook.js +11 -0
- package/dist/auth/session-kernel.d.ts +4 -0
- package/dist/auth/session-kernel.d.ts.map +1 -0
- package/dist/auth/session-kernel.js +21 -0
- package/dist/graph/action.d.ts +22 -0
- package/dist/graph/action.d.ts.map +1 -0
- package/dist/graph/action.js +85 -0
- package/dist/graph/async.d.ts +11 -0
- package/dist/graph/async.d.ts.map +1 -0
- package/dist/graph/async.js +60 -0
- package/dist/graph/call/call.hook.d.ts +21 -0
- package/dist/graph/call/call.hook.d.ts.map +1 -0
- package/dist/graph/call/call.hook.js +23 -0
- package/dist/graph/call/stream.hook.d.ts +28 -0
- package/dist/graph/call/stream.hook.d.ts.map +1 -0
- package/dist/graph/call/stream.hook.js +137 -0
- package/dist/graph/graph.context.d.ts +4 -0
- package/dist/graph/graph.context.d.ts.map +1 -0
- package/dist/graph/graph.context.js +10 -0
- package/dist/graph/guards.error.d.ts +9 -0
- package/dist/graph/guards.error.d.ts.map +1 -0
- package/dist/graph/guards.error.js +7 -0
- package/dist/graph/index.d.ts +20 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +9 -0
- package/dist/graph/memory/base.d.ts +21 -0
- package/dist/graph/memory/base.d.ts.map +1 -0
- package/dist/graph/memory/base.js +33 -0
- package/dist/graph/memory/read/envelope.d.ts +71 -0
- package/dist/graph/memory/read/envelope.d.ts.map +1 -0
- package/dist/graph/memory/read/envelope.js +29 -0
- package/dist/graph/memory/read/idle.d.ts +18 -0
- package/dist/graph/memory/read/idle.d.ts.map +1 -0
- package/dist/graph/memory/read/idle.js +16 -0
- package/dist/graph/memory/read/read.d.ts +9 -0
- package/dist/graph/memory/read/read.d.ts.map +1 -0
- package/dist/graph/memory/read/read.js +87 -0
- package/dist/graph/memory/scope.d.ts +7 -0
- package/dist/graph/memory/scope.d.ts.map +1 -0
- package/dist/graph/memory/scope.js +25 -0
- package/dist/graph/mutate/move.hook.d.ts +7 -0
- package/dist/graph/mutate/move.hook.d.ts.map +1 -0
- package/dist/graph/mutate/move.hook.js +49 -0
- package/dist/graph/mutate/mutate.hook.d.ts +17 -0
- package/dist/graph/mutate/mutate.hook.d.ts.map +1 -0
- package/dist/graph/mutate/mutate.hook.js +45 -0
- package/dist/graph/query/children.hook.d.ts +29 -0
- package/dist/graph/query/children.hook.d.ts.map +1 -0
- package/dist/graph/query/children.hook.js +64 -0
- package/dist/graph/query/graph.hook.d.ts +9 -0
- package/dist/graph/query/graph.hook.d.ts.map +1 -0
- package/dist/graph/query/graph.hook.js +5 -0
- package/dist/graph/query/neighbors.hook.d.ts +7 -0
- package/dist/graph/query/neighbors.hook.d.ts.map +1 -0
- package/dist/graph/query/neighbors.hook.js +79 -0
- package/dist/graph/query/node.hook.d.ts +14 -0
- package/dist/graph/query/node.hook.d.ts.map +1 -0
- package/dist/graph/query/node.hook.js +43 -0
- package/dist/graph/query/query.hook.d.ts +14 -0
- package/dist/graph/query/query.hook.d.ts.map +1 -0
- package/dist/graph/query/query.hook.js +23 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/intents/envelope.d.ts +33 -0
- package/dist/intents/envelope.d.ts.map +1 -0
- package/dist/intents/envelope.js +19 -0
- package/dist/intents/index.d.ts +6 -0
- package/dist/intents/index.d.ts.map +1 -0
- package/dist/intents/index.js +3 -0
- package/dist/intents/listen-intent.hook.d.ts +16 -0
- package/dist/intents/listen-intent.hook.d.ts.map +1 -0
- package/dist/intents/listen-intent.hook.js +75 -0
- package/dist/intents/reply.d.ts +9 -0
- package/dist/intents/reply.d.ts.map +1 -0
- package/dist/intents/reply.js +14 -0
- package/dist/intents/send-intent.hook.d.ts +12 -0
- package/dist/intents/send-intent.hook.d.ts.map +1 -0
- package/dist/intents/send-intent.hook.js +86 -0
- package/dist/navigation/adapters/adapter.d.ts +15 -0
- package/dist/navigation/adapters/adapter.d.ts.map +1 -0
- package/dist/navigation/adapters/adapter.js +1 -0
- package/dist/navigation/adapters/memory.adapter.d.ts +9 -0
- package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -0
- package/dist/navigation/adapters/memory.adapter.js +15 -0
- package/dist/navigation/adapters/url.adapter.d.ts +6 -0
- package/dist/navigation/adapters/url.adapter.d.ts.map +1 -0
- package/dist/navigation/adapters/url.adapter.js +59 -0
- package/dist/navigation/history.d.ts +63 -0
- package/dist/navigation/history.d.ts.map +1 -0
- package/dist/navigation/history.js +144 -0
- package/dist/navigation/hooks/ancestors.hook.d.ts +13 -0
- package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -0
- package/dist/navigation/hooks/ancestors.hook.js +56 -0
- package/dist/navigation/hooks/location.hook.d.ts +4 -0
- package/dist/navigation/hooks/location.hook.d.ts.map +1 -0
- package/dist/navigation/hooks/location.hook.js +17 -0
- package/dist/navigation/hooks/navigate.hook.d.ts +12 -0
- package/dist/navigation/hooks/navigate.hook.d.ts.map +1 -0
- package/dist/navigation/hooks/navigate.hook.js +33 -0
- package/dist/navigation/hooks/scope.hook.d.ts +12 -0
- package/dist/navigation/hooks/scope.hook.d.ts.map +1 -0
- package/dist/navigation/hooks/scope.hook.js +21 -0
- package/dist/navigation/index.d.ts +16 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +10 -0
- package/dist/navigation/link.d.ts +11 -0
- package/dist/navigation/link.d.ts.map +1 -0
- package/dist/navigation/link.js +62 -0
- package/dist/navigation/location.d.ts +48 -0
- package/dist/navigation/location.d.ts.map +1 -0
- package/dist/navigation/location.js +88 -0
- package/dist/navigation/scope.context.d.ts +64 -0
- package/dist/navigation/scope.context.d.ts.map +1 -0
- package/dist/navigation/scope.context.js +178 -0
- package/dist/navigation/snapshot.d.ts +22 -0
- package/dist/navigation/snapshot.d.ts.map +1 -0
- package/dist/navigation/snapshot.js +65 -0
- package/dist/schema/bind-read.d.ts +37 -0
- package/dist/schema/bind-read.d.ts.map +1 -0
- package/dist/schema/bind-read.js +205 -0
- package/dist/schema/binding.d.ts +21 -0
- package/dist/schema/binding.d.ts.map +1 -0
- package/dist/schema/binding.js +55 -0
- package/dist/schema/domain.hook.d.ts +10 -0
- package/dist/schema/domain.hook.d.ts.map +1 -0
- package/dist/schema/domain.hook.js +7 -0
- package/dist/schema/function.hook.d.ts +9 -0
- package/dist/schema/function.hook.d.ts.map +1 -0
- package/dist/schema/function.hook.js +40 -0
- package/dist/schema/index.d.ts +10 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +8 -0
- package/dist/schema/kernel.hook.d.ts +10 -0
- package/dist/schema/kernel.hook.d.ts.map +1 -0
- package/dist/schema/kernel.hook.js +8 -0
- package/dist/schema/method.hook.d.ts +14 -0
- package/dist/schema/method.hook.d.ts.map +1 -0
- package/dist/schema/method.hook.js +49 -0
- package/dist/schema/tag.d.ts +11 -0
- package/dist/schema/tag.d.ts.map +1 -0
- package/dist/schema/tag.js +11 -0
- package/dist/schema/types.d.ts +73 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +1 -0
- package/dist/schema/write.d.ts +15 -0
- package/dist/schema/write.d.ts.map +1 -0
- package/dist/schema/write.js +45 -0
- package/dist/selection/index.d.ts +4 -0
- package/dist/selection/index.d.ts.map +1 -0
- package/dist/selection/index.js +4 -0
- package/dist/selection/live.d.ts +21 -0
- package/dist/selection/live.d.ts.map +1 -0
- package/dist/selection/live.js +116 -0
- package/dist/selection/scope.context.d.ts +26 -0
- package/dist/selection/scope.context.d.ts.map +1 -0
- package/dist/selection/scope.context.js +100 -0
- package/dist/selection/selection.hook.d.ts +4 -0
- package/dist/selection/selection.hook.d.ts.map +1 -0
- package/dist/selection/selection.hook.js +14 -0
- package/dist/session/boot/boot.d.ts +19 -0
- package/dist/session/boot/boot.d.ts.map +1 -0
- package/dist/session/boot/boot.js +45 -0
- package/dist/session/boot/ownership.d.ts +18 -0
- package/dist/session/boot/ownership.d.ts.map +1 -0
- package/dist/session/boot/ownership.js +39 -0
- package/dist/session/boot/status.d.ts +24 -0
- package/dist/session/boot/status.d.ts.map +1 -0
- package/dist/session/boot/status.js +11 -0
- package/dist/session/connection/connection.hook.d.ts +3 -0
- package/dist/session/connection/connection.hook.d.ts.map +1 -0
- package/dist/session/connection/connection.hook.js +12 -0
- package/dist/session/connection/connection.store.d.ts +24 -0
- package/dist/session/connection/connection.store.d.ts.map +1 -0
- package/dist/session/connection/connection.store.js +31 -0
- package/dist/session/index.d.ts +8 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/kernel-client.hook.d.ts +9 -0
- package/dist/session/kernel-client.hook.d.ts.map +1 -0
- package/dist/session/kernel-client.hook.js +5 -0
- package/dist/session/kernel-instance.hook.d.ts +9 -0
- package/dist/session/kernel-instance.hook.d.ts.map +1 -0
- package/dist/session/kernel-instance.hook.js +10 -0
- package/dist/session/provider.d.ts +31 -0
- package/dist/session/provider.d.ts.map +1 -0
- package/dist/session/provider.js +165 -0
- package/dist/session/session.context.d.ts +18 -0
- package/dist/session/session.context.d.ts.map +1 -0
- package/dist/session/session.context.js +8 -0
- package/dist/session/shell.hook.d.ts +4 -0
- package/dist/session/shell.hook.d.ts.map +1 -0
- package/dist/session/shell.hook.js +15 -0
- package/dist/window/adopt.d.ts +27 -0
- package/dist/window/adopt.d.ts.map +1 -0
- package/dist/window/adopt.js +27 -0
- package/dist/window/hooks/close-guard.hook.d.ts +6 -0
- package/dist/window/hooks/close-guard.hook.d.ts.map +1 -0
- package/dist/window/hooks/close-guard.hook.js +90 -0
- package/dist/window/hooks/target-node.hook.d.ts +7 -0
- package/dist/window/hooks/target-node.hook.d.ts.map +1 -0
- package/dist/window/hooks/target-node.hook.js +77 -0
- package/dist/window/hooks/views-for.hook.d.ts +8 -0
- package/dist/window/hooks/views-for.hook.d.ts.map +1 -0
- package/dist/window/hooks/views-for.hook.js +51 -0
- package/dist/window/hooks/window.hook.d.ts +4 -0
- package/dist/window/hooks/window.hook.d.ts.map +1 -0
- package/dist/window/hooks/window.hook.js +14 -0
- package/dist/window/hooks/windows.hook.d.ts +15 -0
- package/dist/window/hooks/windows.hook.d.ts.map +1 -0
- package/dist/window/hooks/windows.hook.js +25 -0
- package/dist/window/host.d.ts +31 -0
- package/dist/window/host.d.ts.map +1 -0
- package/dist/window/host.js +270 -0
- package/dist/window/hub.d.ts +41 -0
- package/dist/window/hub.d.ts.map +1 -0
- package/dist/window/hub.js +100 -0
- package/dist/window/index.d.ts +15 -0
- package/dist/window/index.d.ts.map +1 -0
- package/dist/window/index.js +10 -0
- package/dist/window/lifecycle/mount.d.ts +47 -0
- package/dist/window/lifecycle/mount.d.ts.map +1 -0
- package/dist/window/lifecycle/mount.js +92 -0
- package/dist/window/lifecycle/states.d.ts +33 -0
- package/dist/window/lifecycle/states.d.ts.map +1 -0
- package/dist/window/lifecycle/states.js +7 -0
- package/dist/window/placement.d.ts +33 -0
- package/dist/window/placement.d.ts.map +1 -0
- package/dist/window/placement.js +57 -0
- package/dist/window/stage.d.ts +3 -0
- package/dist/window/stage.d.ts.map +1 -0
- package/dist/window/stage.js +41 -0
- package/package.json +59 -0
- package/src/application/apps/app-host.tsx +113 -0
- package/src/application/apps/app-logo.tsx +56 -0
- package/src/application/apps/apps.hook.ts +81 -0
- package/src/application/apps/open-app.hook.ts +18 -0
- package/src/application/index.ts +22 -0
- package/src/application/roles.hook.ts +41 -0
- package/src/application/spaces/current-space.hook.ts +43 -0
- package/src/application/spaces/current-space.store.ts +110 -0
- package/src/application/spaces/space.hook.ts +41 -0
- package/src/application/spaces/spaces.hook.ts +113 -0
- package/src/application/user/user.hook.ts +27 -0
- package/src/application/user/user.store.ts +85 -0
- package/src/auth/act-as.context.tsx +124 -0
- package/src/auth/auth.hook.ts +36 -0
- package/src/auth/can.hook.ts +149 -0
- package/src/auth/index.ts +6 -0
- package/src/auth/self.hook.ts +14 -0
- package/src/auth/session-kernel.ts +24 -0
- package/src/graph/action.ts +127 -0
- package/src/graph/async.ts +87 -0
- package/src/graph/call/call.hook.ts +42 -0
- package/src/graph/call/stream.hook.ts +200 -0
- package/src/graph/graph.context.ts +14 -0
- package/src/graph/guards.error.ts +58 -0
- package/src/graph/index.ts +20 -0
- package/src/graph/memory/base.ts +50 -0
- package/src/graph/memory/read/envelope.ts +98 -0
- package/src/graph/memory/read/idle.ts +24 -0
- package/src/graph/memory/read/read.ts +103 -0
- package/src/graph/memory/scope.ts +29 -0
- package/src/graph/mutate/move.hook.ts +70 -0
- package/src/graph/mutate/mutate.hook.ts +69 -0
- package/src/graph/query/children.hook.ts +136 -0
- package/src/graph/query/graph.hook.ts +13 -0
- package/src/graph/query/neighbors.hook.ts +124 -0
- package/src/graph/query/node.hook.ts +83 -0
- package/src/graph/query/query.hook.ts +42 -0
- package/src/index.ts +202 -0
- package/src/intents/envelope.ts +52 -0
- package/src/intents/index.ts +6 -0
- package/src/intents/listen-intent.hook.ts +92 -0
- package/src/intents/reply.ts +24 -0
- package/src/intents/send-intent.hook.ts +111 -0
- package/src/navigation/adapters/adapter.ts +13 -0
- package/src/navigation/adapters/memory.adapter.ts +22 -0
- package/src/navigation/adapters/url.adapter.ts +61 -0
- package/src/navigation/history.ts +170 -0
- package/src/navigation/hooks/ancestors.hook.ts +71 -0
- package/src/navigation/hooks/location.hook.ts +21 -0
- package/src/navigation/hooks/navigate.hook.ts +43 -0
- package/src/navigation/hooks/scope.hook.ts +34 -0
- package/src/navigation/index.ts +17 -0
- package/src/navigation/link.tsx +110 -0
- package/src/navigation/location.ts +122 -0
- package/src/navigation/scope.context.tsx +267 -0
- package/src/navigation/snapshot.ts +79 -0
- package/src/schema/bind-read.ts +319 -0
- package/src/schema/binding.ts +91 -0
- package/src/schema/domain.hook.ts +16 -0
- package/src/schema/function.hook.ts +68 -0
- package/src/schema/index.ts +25 -0
- package/src/schema/kernel.hook.ts +17 -0
- package/src/schema/method.hook.ts +103 -0
- package/src/schema/tag.ts +19 -0
- package/src/schema/types.ts +150 -0
- package/src/schema/write.ts +80 -0
- package/src/selection/index.ts +5 -0
- package/src/selection/live.ts +142 -0
- package/src/selection/scope.context.tsx +151 -0
- package/src/selection/selection.hook.ts +18 -0
- package/src/session/boot/boot.ts +57 -0
- package/src/session/boot/ownership.ts +54 -0
- package/src/session/boot/status.ts +32 -0
- package/src/session/connection/connection.hook.ts +16 -0
- package/src/session/connection/connection.store.ts +58 -0
- package/src/session/index.ts +8 -0
- package/src/session/kernel-client.hook.ts +13 -0
- package/src/session/kernel-instance.hook.ts +22 -0
- package/src/session/provider.tsx +205 -0
- package/src/session/session.context.ts +27 -0
- package/src/session/shell.hook.ts +19 -0
- package/src/window/adopt.ts +57 -0
- package/src/window/hooks/close-guard.hook.ts +100 -0
- package/src/window/hooks/target-node.hook.ts +94 -0
- package/src/window/hooks/views-for.hook.ts +82 -0
- package/src/window/hooks/window.hook.ts +18 -0
- package/src/window/hooks/windows.hook.ts +40 -0
- package/src/window/host.tsx +347 -0
- package/src/window/hub.ts +156 -0
- package/src/window/index.ts +17 -0
- package/src/window/lifecycle/mount.ts +134 -0
- package/src/window/lifecycle/states.ts +23 -0
- package/src/window/placement.ts +84 -0
- package/src/window/stage.tsx +46 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { NodeRefInput } from '@astrale-os/kernel-client'
|
|
2
|
+
/**
|
|
3
|
+
* Mount orchestration (API §10) — resolve a `ViewSource` to something `shell.mount`
|
|
4
|
+
* accepts (url + handshake + functionId), the stable remount key, the delivered
|
|
5
|
+
* target id, the handshake-fallback predicate, and the parent→child setTarget
|
|
6
|
+
* hot-swap. A one-call `View.resolve` kernel contract does not exist yet — the
|
|
7
|
+
* bare-ref path is the honest subset, G5.
|
|
8
|
+
*/
|
|
9
|
+
import type { KernelClient, Shell } from '@astrale-os/shell'
|
|
10
|
+
|
|
11
|
+
/** A live graph node, derived from the shell kernel read surface (G8 seam). */
|
|
12
|
+
export type Node = NonNullable<Awaited<ReturnType<KernelClient['get']>>>
|
|
13
|
+
|
|
14
|
+
/** A View function resolved to something mountable (url + optional handshake). */
|
|
15
|
+
export interface ViewDescriptor {
|
|
16
|
+
readonly id: string
|
|
17
|
+
readonly path: string
|
|
18
|
+
readonly url?: string
|
|
19
|
+
readonly handshake?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* What a `ViewHost` mounts:
|
|
24
|
+
* - `{ view }` — a View function (descriptor or ref), resolved to url + handshake.
|
|
25
|
+
* - `{ url }` — a handshake-less hosted view; mounts immediately (no 5s wait).
|
|
26
|
+
*/
|
|
27
|
+
export type ViewSource = { readonly view: NodeRefInput | ViewDescriptor } | { readonly url: string }
|
|
28
|
+
|
|
29
|
+
export interface ResolvedSource {
|
|
30
|
+
readonly url: string
|
|
31
|
+
readonly handshake: 'shell' | 'none'
|
|
32
|
+
readonly functionId: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isViewDescriptor(view: NodeRefInput | ViewDescriptor): view is ViewDescriptor {
|
|
36
|
+
return typeof view === 'object' && view !== null && 'id' in view && 'path' in view
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Last path segment or host, alnum-only — a stable-ish functionId from a url. */
|
|
40
|
+
function slugOfUrl(url: string): string {
|
|
41
|
+
const trimmed = url.replace(/[#?].*$/, '').replace(/\/+$/, '')
|
|
42
|
+
const tail = trimmed.split('/').filter(Boolean).pop() ?? 'view'
|
|
43
|
+
return tail.replace(/[^a-z0-9]/gi, '').slice(-32) || 'view'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** A ref addressable by the kernel read surface (`get`). `@<id>` for bare ids. */
|
|
47
|
+
function toPath(ref: NodeRefInput): string {
|
|
48
|
+
if (typeof ref === 'string') {
|
|
49
|
+
return ref.startsWith('/') || ref.startsWith('@') ? ref : `@${ref}`
|
|
50
|
+
}
|
|
51
|
+
const obj = ref as { id?: string; path?: { raw?: string } }
|
|
52
|
+
if (obj.path?.raw !== undefined) return obj.path.raw
|
|
53
|
+
if (obj.id !== undefined) return `@${obj.id}`
|
|
54
|
+
throw new Error('ViewHost: unresolvable view ref')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function resolveViewRef(
|
|
58
|
+
kernel: KernelClient,
|
|
59
|
+
ref: NodeRefInput,
|
|
60
|
+
handshakeHint?: string,
|
|
61
|
+
): Promise<ResolvedSource> {
|
|
62
|
+
const node = await kernel.get(toPath(ref))
|
|
63
|
+
if (node === null) throw new Error(`ViewHost: view not found (${toPath(ref)})`)
|
|
64
|
+
const props = (node as { id?: string; props?: Record<string, unknown> }).props ?? {}
|
|
65
|
+
const url = props.url
|
|
66
|
+
if (typeof url !== 'string' || url.length === 0) {
|
|
67
|
+
throw new Error('ViewHost: resolved view has no url')
|
|
68
|
+
}
|
|
69
|
+
const handshake = normalizeHandshake(handshakeHint ?? props.handshake)
|
|
70
|
+
const id = (node as { id?: string }).id ?? slugOfUrl(url)
|
|
71
|
+
return { url, handshake, functionId: id }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function normalizeHandshake(value: unknown): 'shell' | 'none' {
|
|
75
|
+
return value === 'none' ? 'none' : 'shell'
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Resolve a source; may hit the kernel for a bare/urless View ref (G5). */
|
|
79
|
+
export async function resolveSource(
|
|
80
|
+
kernel: KernelClient,
|
|
81
|
+
source: ViewSource,
|
|
82
|
+
): Promise<ResolvedSource> {
|
|
83
|
+
if ('url' in source) {
|
|
84
|
+
return { url: source.url, handshake: 'none', functionId: slugOfUrl(source.url) }
|
|
85
|
+
}
|
|
86
|
+
const view = source.view
|
|
87
|
+
if (isViewDescriptor(view)) {
|
|
88
|
+
if (view.url !== undefined && view.url.length > 0) {
|
|
89
|
+
return {
|
|
90
|
+
url: view.url,
|
|
91
|
+
handshake: normalizeHandshake(view.handshake),
|
|
92
|
+
functionId: view.id,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return resolveViewRef(kernel, view.id, view.handshake)
|
|
96
|
+
}
|
|
97
|
+
return resolveViewRef(kernel, view)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** A stable remount key: the same source identity must not remount. */
|
|
101
|
+
export function sourceKey(source: ViewSource): string {
|
|
102
|
+
if ('url' in source) return `url:${source.url}`
|
|
103
|
+
const view = source.view
|
|
104
|
+
if (isViewDescriptor(view)) return `view:${view.id}:${view.url ?? ''}:${view.handshake ?? ''}`
|
|
105
|
+
if (typeof view === 'string') return `ref:${view}`
|
|
106
|
+
const obj = view as { id?: string; path?: { raw?: string } }
|
|
107
|
+
return `ref:${obj.id ?? obj.path?.raw ?? '?'}`
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** The bare node id delivered as `targetNodeId` at mount / retarget. */
|
|
111
|
+
export function refToId(ref: NodeRefInput | undefined): string | undefined {
|
|
112
|
+
if (ref === undefined) return undefined
|
|
113
|
+
if (typeof ref === 'string') return ref.startsWith('@') ? ref.slice(1) : ref
|
|
114
|
+
const obj = ref as { id?: string }
|
|
115
|
+
return obj.id
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Fallbackable = the view didn't speak the shell protocol (timeout/failed), not a
|
|
120
|
+
* security refusal (origin mismatch) — only the former downgrades to plain.
|
|
121
|
+
*/
|
|
122
|
+
export function isFallbackableHandshakeError(err: unknown): boolean {
|
|
123
|
+
const code = (err as { code?: unknown } | null)?.code
|
|
124
|
+
return code === 'HANDSHAKE_TIMEOUT' || code === 'HANDSHAKE_FAILED'
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Parent → child hot-swap of the target node (no remount) — API §10 setTarget. */
|
|
128
|
+
export function sendSetTarget(shell: Shell, windowId: string, nodeId: string): void {
|
|
129
|
+
shell.children.send(windowId, {
|
|
130
|
+
type: 'intent',
|
|
131
|
+
version: 1,
|
|
132
|
+
envelope: { name: 'setTarget', payload: { nodeId }, sender: { windowId: '<parent>' } },
|
|
133
|
+
})
|
|
134
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The WindowState phase machine (API §10) — the lifecycle of a hosted view as the
|
|
3
|
+
* React face observes it. Distinct from the shell's own `WindowState`
|
|
4
|
+
* (`active|hidden|closing|closed`): this is the phase a `ViewHost`/`AppHost`
|
|
5
|
+
* renders around.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Lifecycle of a hosted view as the React face observes it (API §10).
|
|
10
|
+
*
|
|
11
|
+
* `ready.downgraded` marks a mount that fell back to a plain iframe after a
|
|
12
|
+
* fallbackable handshake error. It rides here (not on the shell `Window`) until
|
|
13
|
+
* the shell `Window` grows a first-class flag — flagged in the module report.
|
|
14
|
+
*
|
|
15
|
+
* `crashed.windowId` is OPTIONAL: a crash before a window exists (a session-open
|
|
16
|
+
* failure, a pre-mount source-resolution failure) has no id to report — the type
|
|
17
|
+
* says so rather than carrying a placeholder `''`.
|
|
18
|
+
*/
|
|
19
|
+
export type WindowState =
|
|
20
|
+
| { readonly phase: 'mounting' }
|
|
21
|
+
| { readonly phase: 'ready'; readonly windowId: string; readonly downgraded?: boolean }
|
|
22
|
+
| { readonly phase: 'crashed'; readonly windowId?: string; readonly error?: unknown }
|
|
23
|
+
| { readonly phase: 'closed'; readonly windowId: string; readonly refusal?: string }
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slot geometry (API §10) — the physical iframe-slot layer over a stage container
|
|
3
|
+
* (measure + project). Slots live in the stage (imperative DOM), insulated from
|
|
4
|
+
* React reconciliation of the hosts; only a slot's box is repositioned, so a
|
|
5
|
+
* healthy iframe never reloads on reorder/re-key/re-parent.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Viewport-space box a host projects onto its stage slot. */
|
|
9
|
+
export interface SlotRect {
|
|
10
|
+
readonly top: number
|
|
11
|
+
readonly left: number
|
|
12
|
+
readonly width: number
|
|
13
|
+
readonly height: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* One persistent slot inside the stage. Its `element` is the mount host handed
|
|
18
|
+
* to `shell.mount`; the element NEVER moves in the DOM while the owning host
|
|
19
|
+
* reorders/re-keys/re-parents — only its box is repositioned via `place`.
|
|
20
|
+
*/
|
|
21
|
+
export interface StageSlot {
|
|
22
|
+
readonly element: HTMLElement
|
|
23
|
+
place(rect: SlotRect): void
|
|
24
|
+
release(): void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface StageController {
|
|
28
|
+
acquire(): StageSlot
|
|
29
|
+
dispose(): void
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Build the slot layer over a stage container element (imperative, no React). */
|
|
33
|
+
export function createStageController(container: HTMLElement): StageController {
|
|
34
|
+
const slots = new Set<HTMLElement>()
|
|
35
|
+
let disposed = false
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
acquire() {
|
|
39
|
+
const element = container.ownerDocument.createElement('div')
|
|
40
|
+
element.dataset.astraleViewSlot = ''
|
|
41
|
+
element.style.position = 'absolute'
|
|
42
|
+
element.style.top = '0'
|
|
43
|
+
element.style.left = '0'
|
|
44
|
+
element.style.pointerEvents = 'auto'
|
|
45
|
+
container.appendChild(element)
|
|
46
|
+
slots.add(element)
|
|
47
|
+
|
|
48
|
+
let released = false
|
|
49
|
+
return {
|
|
50
|
+
element,
|
|
51
|
+
place(rect) {
|
|
52
|
+
// translate + explicit box, so a reflow of the container never drifts
|
|
53
|
+
// the slot off its anchor.
|
|
54
|
+
element.style.transform = `translate(${rect.left}px, ${rect.top}px)`
|
|
55
|
+
element.style.width = `${rect.width}px`
|
|
56
|
+
element.style.height = `${rect.height}px`
|
|
57
|
+
},
|
|
58
|
+
release() {
|
|
59
|
+
if (released) return
|
|
60
|
+
released = true
|
|
61
|
+
slots.delete(element)
|
|
62
|
+
element.remove()
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
dispose() {
|
|
68
|
+
if (disposed) return
|
|
69
|
+
disposed = true
|
|
70
|
+
for (const el of slots) el.remove()
|
|
71
|
+
slots.clear()
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Measure an anchor element's viewport box. */
|
|
77
|
+
export function rectOf(el: HTMLElement): SlotRect {
|
|
78
|
+
const r = el.getBoundingClientRect()
|
|
79
|
+
return { top: r.top, left: r.left, width: r.width, height: r.height }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function sameRect(a: SlotRect, b: SlotRect): boolean {
|
|
83
|
+
return a.top === b.top && a.left === b.left && a.width === b.width && a.height === b.height
|
|
84
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { CSSProperties, ReactElement } from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ViewStage (API §10) — the fixed-positioning layer that physically owns every
|
|
5
|
+
* iframe for the `ViewHost`/`AppHost`s in the tree. Mount it ONCE near the root.
|
|
6
|
+
* Reordering / re-parenting / re-keying hosts never reloads a healthy iframe:
|
|
7
|
+
* each iframe lives in a stage slot (imperative DOM), insulated from React
|
|
8
|
+
* reconciliation of the hosts; only the slot's box is repositioned.
|
|
9
|
+
*/
|
|
10
|
+
import { useEffect, useMemo, useRef } from 'react'
|
|
11
|
+
|
|
12
|
+
import { useShell } from '../session/shell.hook'
|
|
13
|
+
import { getStageHub } from './hub'
|
|
14
|
+
import { createStageController } from './placement'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A full-viewport overlay that does not intercept pointer events — individual
|
|
18
|
+
* slots re-enable them, so only the iframes are interactive, not the gaps.
|
|
19
|
+
*/
|
|
20
|
+
const STAGE_STYLE: CSSProperties = {
|
|
21
|
+
position: 'fixed',
|
|
22
|
+
top: 0,
|
|
23
|
+
left: 0,
|
|
24
|
+
right: 0,
|
|
25
|
+
bottom: 0,
|
|
26
|
+
pointerEvents: 'none',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function ViewStage(): ReactElement {
|
|
30
|
+
const shell = useShell()
|
|
31
|
+
const hub = useMemo(() => getStageHub(shell), [shell])
|
|
32
|
+
const containerRef = useRef<HTMLDivElement | null>(null)
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const container = containerRef.current
|
|
36
|
+
if (container === null) return
|
|
37
|
+
const controller = createStageController(container)
|
|
38
|
+
hub.setController(controller)
|
|
39
|
+
return () => {
|
|
40
|
+
hub.setController(null)
|
|
41
|
+
controller.dispose()
|
|
42
|
+
}
|
|
43
|
+
}, [hub])
|
|
44
|
+
|
|
45
|
+
return <div ref={containerRef} data-astrale-view-stage="" style={STAGE_STYLE} />
|
|
46
|
+
}
|