@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.
Files changed (378) hide show
  1. package/LICENSE +202 -0
  2. package/dist/application/apps/app-host.d.ts +31 -0
  3. package/dist/application/apps/app-host.d.ts.map +1 -0
  4. package/dist/application/apps/app-host.js +59 -0
  5. package/dist/application/apps/app-logo.d.ts +19 -0
  6. package/dist/application/apps/app-logo.d.ts.map +1 -0
  7. package/dist/application/apps/app-logo.js +31 -0
  8. package/dist/application/apps/apps.hook.d.ts +12 -0
  9. package/dist/application/apps/apps.hook.d.ts.map +1 -0
  10. package/dist/application/apps/apps.hook.js +51 -0
  11. package/dist/application/apps/open-app.hook.d.ts +10 -0
  12. package/dist/application/apps/open-app.hook.d.ts.map +1 -0
  13. package/dist/application/apps/open-app.hook.js +7 -0
  14. package/dist/application/index.d.ts +18 -0
  15. package/dist/application/index.d.ts.map +1 -0
  16. package/dist/application/index.js +12 -0
  17. package/dist/application/roles.hook.d.ts +7 -0
  18. package/dist/application/roles.hook.d.ts.map +1 -0
  19. package/dist/application/roles.hook.js +23 -0
  20. package/dist/application/spaces/current-space.hook.d.ts +7 -0
  21. package/dist/application/spaces/current-space.hook.d.ts.map +1 -0
  22. package/dist/application/spaces/current-space.hook.js +27 -0
  23. package/dist/application/spaces/current-space.store.d.ts +32 -0
  24. package/dist/application/spaces/current-space.store.d.ts.map +1 -0
  25. package/dist/application/spaces/current-space.store.js +79 -0
  26. package/dist/application/spaces/space.hook.d.ts +5 -0
  27. package/dist/application/spaces/space.hook.d.ts.map +1 -0
  28. package/dist/application/spaces/space.hook.js +25 -0
  29. package/dist/application/spaces/spaces.hook.d.ts +14 -0
  30. package/dist/application/spaces/spaces.hook.d.ts.map +1 -0
  31. package/dist/application/spaces/spaces.hook.js +82 -0
  32. package/dist/application/user/user.hook.d.ts +10 -0
  33. package/dist/application/user/user.hook.d.ts.map +1 -0
  34. package/dist/application/user/user.hook.js +19 -0
  35. package/dist/application/user/user.store.d.ts +35 -0
  36. package/dist/application/user/user.store.d.ts.map +1 -0
  37. package/dist/application/user/user.store.js +51 -0
  38. package/dist/auth/act-as.context.d.ts +40 -0
  39. package/dist/auth/act-as.context.d.ts.map +1 -0
  40. package/dist/auth/act-as.context.js +84 -0
  41. package/dist/auth/auth.hook.d.ts +3 -0
  42. package/dist/auth/auth.hook.d.ts.map +1 -0
  43. package/dist/auth/auth.hook.js +25 -0
  44. package/dist/auth/can.hook.d.ts +40 -0
  45. package/dist/auth/can.hook.d.ts.map +1 -0
  46. package/dist/auth/can.hook.js +119 -0
  47. package/dist/auth/index.d.ts +6 -0
  48. package/dist/auth/index.d.ts.map +1 -0
  49. package/dist/auth/index.js +5 -0
  50. package/dist/auth/self.hook.d.ts +3 -0
  51. package/dist/auth/self.hook.d.ts.map +1 -0
  52. package/dist/auth/self.hook.js +11 -0
  53. package/dist/auth/session-kernel.d.ts +4 -0
  54. package/dist/auth/session-kernel.d.ts.map +1 -0
  55. package/dist/auth/session-kernel.js +21 -0
  56. package/dist/graph/action.d.ts +22 -0
  57. package/dist/graph/action.d.ts.map +1 -0
  58. package/dist/graph/action.js +85 -0
  59. package/dist/graph/async.d.ts +11 -0
  60. package/dist/graph/async.d.ts.map +1 -0
  61. package/dist/graph/async.js +60 -0
  62. package/dist/graph/call/call.hook.d.ts +21 -0
  63. package/dist/graph/call/call.hook.d.ts.map +1 -0
  64. package/dist/graph/call/call.hook.js +23 -0
  65. package/dist/graph/call/stream.hook.d.ts +28 -0
  66. package/dist/graph/call/stream.hook.d.ts.map +1 -0
  67. package/dist/graph/call/stream.hook.js +137 -0
  68. package/dist/graph/graph.context.d.ts +4 -0
  69. package/dist/graph/graph.context.d.ts.map +1 -0
  70. package/dist/graph/graph.context.js +10 -0
  71. package/dist/graph/guards.error.d.ts +9 -0
  72. package/dist/graph/guards.error.d.ts.map +1 -0
  73. package/dist/graph/guards.error.js +7 -0
  74. package/dist/graph/index.d.ts +20 -0
  75. package/dist/graph/index.d.ts.map +1 -0
  76. package/dist/graph/index.js +9 -0
  77. package/dist/graph/memory/base.d.ts +21 -0
  78. package/dist/graph/memory/base.d.ts.map +1 -0
  79. package/dist/graph/memory/base.js +33 -0
  80. package/dist/graph/memory/read/envelope.d.ts +71 -0
  81. package/dist/graph/memory/read/envelope.d.ts.map +1 -0
  82. package/dist/graph/memory/read/envelope.js +29 -0
  83. package/dist/graph/memory/read/idle.d.ts +18 -0
  84. package/dist/graph/memory/read/idle.d.ts.map +1 -0
  85. package/dist/graph/memory/read/idle.js +16 -0
  86. package/dist/graph/memory/read/read.d.ts +9 -0
  87. package/dist/graph/memory/read/read.d.ts.map +1 -0
  88. package/dist/graph/memory/read/read.js +87 -0
  89. package/dist/graph/memory/scope.d.ts +7 -0
  90. package/dist/graph/memory/scope.d.ts.map +1 -0
  91. package/dist/graph/memory/scope.js +25 -0
  92. package/dist/graph/mutate/move.hook.d.ts +7 -0
  93. package/dist/graph/mutate/move.hook.d.ts.map +1 -0
  94. package/dist/graph/mutate/move.hook.js +49 -0
  95. package/dist/graph/mutate/mutate.hook.d.ts +17 -0
  96. package/dist/graph/mutate/mutate.hook.d.ts.map +1 -0
  97. package/dist/graph/mutate/mutate.hook.js +45 -0
  98. package/dist/graph/query/children.hook.d.ts +29 -0
  99. package/dist/graph/query/children.hook.d.ts.map +1 -0
  100. package/dist/graph/query/children.hook.js +64 -0
  101. package/dist/graph/query/graph.hook.d.ts +9 -0
  102. package/dist/graph/query/graph.hook.d.ts.map +1 -0
  103. package/dist/graph/query/graph.hook.js +5 -0
  104. package/dist/graph/query/neighbors.hook.d.ts +7 -0
  105. package/dist/graph/query/neighbors.hook.d.ts.map +1 -0
  106. package/dist/graph/query/neighbors.hook.js +79 -0
  107. package/dist/graph/query/node.hook.d.ts +14 -0
  108. package/dist/graph/query/node.hook.d.ts.map +1 -0
  109. package/dist/graph/query/node.hook.js +43 -0
  110. package/dist/graph/query/query.hook.d.ts +14 -0
  111. package/dist/graph/query/query.hook.d.ts.map +1 -0
  112. package/dist/graph/query/query.hook.js +23 -0
  113. package/dist/index.d.ts +43 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +34 -0
  116. package/dist/intents/envelope.d.ts +33 -0
  117. package/dist/intents/envelope.d.ts.map +1 -0
  118. package/dist/intents/envelope.js +19 -0
  119. package/dist/intents/index.d.ts +6 -0
  120. package/dist/intents/index.d.ts.map +1 -0
  121. package/dist/intents/index.js +3 -0
  122. package/dist/intents/listen-intent.hook.d.ts +16 -0
  123. package/dist/intents/listen-intent.hook.d.ts.map +1 -0
  124. package/dist/intents/listen-intent.hook.js +75 -0
  125. package/dist/intents/reply.d.ts +9 -0
  126. package/dist/intents/reply.d.ts.map +1 -0
  127. package/dist/intents/reply.js +14 -0
  128. package/dist/intents/send-intent.hook.d.ts +12 -0
  129. package/dist/intents/send-intent.hook.d.ts.map +1 -0
  130. package/dist/intents/send-intent.hook.js +86 -0
  131. package/dist/navigation/adapters/adapter.d.ts +15 -0
  132. package/dist/navigation/adapters/adapter.d.ts.map +1 -0
  133. package/dist/navigation/adapters/adapter.js +1 -0
  134. package/dist/navigation/adapters/memory.adapter.d.ts +9 -0
  135. package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -0
  136. package/dist/navigation/adapters/memory.adapter.js +15 -0
  137. package/dist/navigation/adapters/url.adapter.d.ts +6 -0
  138. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -0
  139. package/dist/navigation/adapters/url.adapter.js +59 -0
  140. package/dist/navigation/history.d.ts +63 -0
  141. package/dist/navigation/history.d.ts.map +1 -0
  142. package/dist/navigation/history.js +144 -0
  143. package/dist/navigation/hooks/ancestors.hook.d.ts +13 -0
  144. package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -0
  145. package/dist/navigation/hooks/ancestors.hook.js +56 -0
  146. package/dist/navigation/hooks/location.hook.d.ts +4 -0
  147. package/dist/navigation/hooks/location.hook.d.ts.map +1 -0
  148. package/dist/navigation/hooks/location.hook.js +17 -0
  149. package/dist/navigation/hooks/navigate.hook.d.ts +12 -0
  150. package/dist/navigation/hooks/navigate.hook.d.ts.map +1 -0
  151. package/dist/navigation/hooks/navigate.hook.js +33 -0
  152. package/dist/navigation/hooks/scope.hook.d.ts +12 -0
  153. package/dist/navigation/hooks/scope.hook.d.ts.map +1 -0
  154. package/dist/navigation/hooks/scope.hook.js +21 -0
  155. package/dist/navigation/index.d.ts +16 -0
  156. package/dist/navigation/index.d.ts.map +1 -0
  157. package/dist/navigation/index.js +10 -0
  158. package/dist/navigation/link.d.ts +11 -0
  159. package/dist/navigation/link.d.ts.map +1 -0
  160. package/dist/navigation/link.js +62 -0
  161. package/dist/navigation/location.d.ts +48 -0
  162. package/dist/navigation/location.d.ts.map +1 -0
  163. package/dist/navigation/location.js +88 -0
  164. package/dist/navigation/scope.context.d.ts +64 -0
  165. package/dist/navigation/scope.context.d.ts.map +1 -0
  166. package/dist/navigation/scope.context.js +178 -0
  167. package/dist/navigation/snapshot.d.ts +22 -0
  168. package/dist/navigation/snapshot.d.ts.map +1 -0
  169. package/dist/navigation/snapshot.js +65 -0
  170. package/dist/schema/bind-read.d.ts +37 -0
  171. package/dist/schema/bind-read.d.ts.map +1 -0
  172. package/dist/schema/bind-read.js +205 -0
  173. package/dist/schema/binding.d.ts +21 -0
  174. package/dist/schema/binding.d.ts.map +1 -0
  175. package/dist/schema/binding.js +55 -0
  176. package/dist/schema/domain.hook.d.ts +10 -0
  177. package/dist/schema/domain.hook.d.ts.map +1 -0
  178. package/dist/schema/domain.hook.js +7 -0
  179. package/dist/schema/function.hook.d.ts +9 -0
  180. package/dist/schema/function.hook.d.ts.map +1 -0
  181. package/dist/schema/function.hook.js +40 -0
  182. package/dist/schema/index.d.ts +10 -0
  183. package/dist/schema/index.d.ts.map +1 -0
  184. package/dist/schema/index.js +8 -0
  185. package/dist/schema/kernel.hook.d.ts +10 -0
  186. package/dist/schema/kernel.hook.d.ts.map +1 -0
  187. package/dist/schema/kernel.hook.js +8 -0
  188. package/dist/schema/method.hook.d.ts +14 -0
  189. package/dist/schema/method.hook.d.ts.map +1 -0
  190. package/dist/schema/method.hook.js +49 -0
  191. package/dist/schema/tag.d.ts +11 -0
  192. package/dist/schema/tag.d.ts.map +1 -0
  193. package/dist/schema/tag.js +11 -0
  194. package/dist/schema/types.d.ts +73 -0
  195. package/dist/schema/types.d.ts.map +1 -0
  196. package/dist/schema/types.js +1 -0
  197. package/dist/schema/write.d.ts +15 -0
  198. package/dist/schema/write.d.ts.map +1 -0
  199. package/dist/schema/write.js +45 -0
  200. package/dist/selection/index.d.ts +4 -0
  201. package/dist/selection/index.d.ts.map +1 -0
  202. package/dist/selection/index.js +4 -0
  203. package/dist/selection/live.d.ts +21 -0
  204. package/dist/selection/live.d.ts.map +1 -0
  205. package/dist/selection/live.js +116 -0
  206. package/dist/selection/scope.context.d.ts +26 -0
  207. package/dist/selection/scope.context.d.ts.map +1 -0
  208. package/dist/selection/scope.context.js +100 -0
  209. package/dist/selection/selection.hook.d.ts +4 -0
  210. package/dist/selection/selection.hook.d.ts.map +1 -0
  211. package/dist/selection/selection.hook.js +14 -0
  212. package/dist/session/boot/boot.d.ts +19 -0
  213. package/dist/session/boot/boot.d.ts.map +1 -0
  214. package/dist/session/boot/boot.js +45 -0
  215. package/dist/session/boot/ownership.d.ts +18 -0
  216. package/dist/session/boot/ownership.d.ts.map +1 -0
  217. package/dist/session/boot/ownership.js +39 -0
  218. package/dist/session/boot/status.d.ts +24 -0
  219. package/dist/session/boot/status.d.ts.map +1 -0
  220. package/dist/session/boot/status.js +11 -0
  221. package/dist/session/connection/connection.hook.d.ts +3 -0
  222. package/dist/session/connection/connection.hook.d.ts.map +1 -0
  223. package/dist/session/connection/connection.hook.js +12 -0
  224. package/dist/session/connection/connection.store.d.ts +24 -0
  225. package/dist/session/connection/connection.store.d.ts.map +1 -0
  226. package/dist/session/connection/connection.store.js +31 -0
  227. package/dist/session/index.d.ts +8 -0
  228. package/dist/session/index.d.ts.map +1 -0
  229. package/dist/session/index.js +6 -0
  230. package/dist/session/kernel-client.hook.d.ts +9 -0
  231. package/dist/session/kernel-client.hook.d.ts.map +1 -0
  232. package/dist/session/kernel-client.hook.js +5 -0
  233. package/dist/session/kernel-instance.hook.d.ts +9 -0
  234. package/dist/session/kernel-instance.hook.d.ts.map +1 -0
  235. package/dist/session/kernel-instance.hook.js +10 -0
  236. package/dist/session/provider.d.ts +31 -0
  237. package/dist/session/provider.d.ts.map +1 -0
  238. package/dist/session/provider.js +165 -0
  239. package/dist/session/session.context.d.ts +18 -0
  240. package/dist/session/session.context.d.ts.map +1 -0
  241. package/dist/session/session.context.js +8 -0
  242. package/dist/session/shell.hook.d.ts +4 -0
  243. package/dist/session/shell.hook.d.ts.map +1 -0
  244. package/dist/session/shell.hook.js +15 -0
  245. package/dist/window/adopt.d.ts +27 -0
  246. package/dist/window/adopt.d.ts.map +1 -0
  247. package/dist/window/adopt.js +27 -0
  248. package/dist/window/hooks/close-guard.hook.d.ts +6 -0
  249. package/dist/window/hooks/close-guard.hook.d.ts.map +1 -0
  250. package/dist/window/hooks/close-guard.hook.js +90 -0
  251. package/dist/window/hooks/target-node.hook.d.ts +7 -0
  252. package/dist/window/hooks/target-node.hook.d.ts.map +1 -0
  253. package/dist/window/hooks/target-node.hook.js +77 -0
  254. package/dist/window/hooks/views-for.hook.d.ts +8 -0
  255. package/dist/window/hooks/views-for.hook.d.ts.map +1 -0
  256. package/dist/window/hooks/views-for.hook.js +51 -0
  257. package/dist/window/hooks/window.hook.d.ts +4 -0
  258. package/dist/window/hooks/window.hook.d.ts.map +1 -0
  259. package/dist/window/hooks/window.hook.js +14 -0
  260. package/dist/window/hooks/windows.hook.d.ts +15 -0
  261. package/dist/window/hooks/windows.hook.d.ts.map +1 -0
  262. package/dist/window/hooks/windows.hook.js +25 -0
  263. package/dist/window/host.d.ts +31 -0
  264. package/dist/window/host.d.ts.map +1 -0
  265. package/dist/window/host.js +270 -0
  266. package/dist/window/hub.d.ts +41 -0
  267. package/dist/window/hub.d.ts.map +1 -0
  268. package/dist/window/hub.js +100 -0
  269. package/dist/window/index.d.ts +15 -0
  270. package/dist/window/index.d.ts.map +1 -0
  271. package/dist/window/index.js +10 -0
  272. package/dist/window/lifecycle/mount.d.ts +47 -0
  273. package/dist/window/lifecycle/mount.d.ts.map +1 -0
  274. package/dist/window/lifecycle/mount.js +92 -0
  275. package/dist/window/lifecycle/states.d.ts +33 -0
  276. package/dist/window/lifecycle/states.d.ts.map +1 -0
  277. package/dist/window/lifecycle/states.js +7 -0
  278. package/dist/window/placement.d.ts +33 -0
  279. package/dist/window/placement.d.ts.map +1 -0
  280. package/dist/window/placement.js +57 -0
  281. package/dist/window/stage.d.ts +3 -0
  282. package/dist/window/stage.d.ts.map +1 -0
  283. package/dist/window/stage.js +41 -0
  284. package/package.json +59 -0
  285. package/src/application/apps/app-host.tsx +113 -0
  286. package/src/application/apps/app-logo.tsx +56 -0
  287. package/src/application/apps/apps.hook.ts +81 -0
  288. package/src/application/apps/open-app.hook.ts +18 -0
  289. package/src/application/index.ts +22 -0
  290. package/src/application/roles.hook.ts +41 -0
  291. package/src/application/spaces/current-space.hook.ts +43 -0
  292. package/src/application/spaces/current-space.store.ts +110 -0
  293. package/src/application/spaces/space.hook.ts +41 -0
  294. package/src/application/spaces/spaces.hook.ts +113 -0
  295. package/src/application/user/user.hook.ts +27 -0
  296. package/src/application/user/user.store.ts +85 -0
  297. package/src/auth/act-as.context.tsx +124 -0
  298. package/src/auth/auth.hook.ts +36 -0
  299. package/src/auth/can.hook.ts +149 -0
  300. package/src/auth/index.ts +6 -0
  301. package/src/auth/self.hook.ts +14 -0
  302. package/src/auth/session-kernel.ts +24 -0
  303. package/src/graph/action.ts +127 -0
  304. package/src/graph/async.ts +87 -0
  305. package/src/graph/call/call.hook.ts +42 -0
  306. package/src/graph/call/stream.hook.ts +200 -0
  307. package/src/graph/graph.context.ts +14 -0
  308. package/src/graph/guards.error.ts +58 -0
  309. package/src/graph/index.ts +20 -0
  310. package/src/graph/memory/base.ts +50 -0
  311. package/src/graph/memory/read/envelope.ts +98 -0
  312. package/src/graph/memory/read/idle.ts +24 -0
  313. package/src/graph/memory/read/read.ts +103 -0
  314. package/src/graph/memory/scope.ts +29 -0
  315. package/src/graph/mutate/move.hook.ts +70 -0
  316. package/src/graph/mutate/mutate.hook.ts +69 -0
  317. package/src/graph/query/children.hook.ts +136 -0
  318. package/src/graph/query/graph.hook.ts +13 -0
  319. package/src/graph/query/neighbors.hook.ts +124 -0
  320. package/src/graph/query/node.hook.ts +83 -0
  321. package/src/graph/query/query.hook.ts +42 -0
  322. package/src/index.ts +202 -0
  323. package/src/intents/envelope.ts +52 -0
  324. package/src/intents/index.ts +6 -0
  325. package/src/intents/listen-intent.hook.ts +92 -0
  326. package/src/intents/reply.ts +24 -0
  327. package/src/intents/send-intent.hook.ts +111 -0
  328. package/src/navigation/adapters/adapter.ts +13 -0
  329. package/src/navigation/adapters/memory.adapter.ts +22 -0
  330. package/src/navigation/adapters/url.adapter.ts +61 -0
  331. package/src/navigation/history.ts +170 -0
  332. package/src/navigation/hooks/ancestors.hook.ts +71 -0
  333. package/src/navigation/hooks/location.hook.ts +21 -0
  334. package/src/navigation/hooks/navigate.hook.ts +43 -0
  335. package/src/navigation/hooks/scope.hook.ts +34 -0
  336. package/src/navigation/index.ts +17 -0
  337. package/src/navigation/link.tsx +110 -0
  338. package/src/navigation/location.ts +122 -0
  339. package/src/navigation/scope.context.tsx +267 -0
  340. package/src/navigation/snapshot.ts +79 -0
  341. package/src/schema/bind-read.ts +319 -0
  342. package/src/schema/binding.ts +91 -0
  343. package/src/schema/domain.hook.ts +16 -0
  344. package/src/schema/function.hook.ts +68 -0
  345. package/src/schema/index.ts +25 -0
  346. package/src/schema/kernel.hook.ts +17 -0
  347. package/src/schema/method.hook.ts +103 -0
  348. package/src/schema/tag.ts +19 -0
  349. package/src/schema/types.ts +150 -0
  350. package/src/schema/write.ts +80 -0
  351. package/src/selection/index.ts +5 -0
  352. package/src/selection/live.ts +142 -0
  353. package/src/selection/scope.context.tsx +151 -0
  354. package/src/selection/selection.hook.ts +18 -0
  355. package/src/session/boot/boot.ts +57 -0
  356. package/src/session/boot/ownership.ts +54 -0
  357. package/src/session/boot/status.ts +32 -0
  358. package/src/session/connection/connection.hook.ts +16 -0
  359. package/src/session/connection/connection.store.ts +58 -0
  360. package/src/session/index.ts +8 -0
  361. package/src/session/kernel-client.hook.ts +13 -0
  362. package/src/session/kernel-instance.hook.ts +22 -0
  363. package/src/session/provider.tsx +205 -0
  364. package/src/session/session.context.ts +27 -0
  365. package/src/session/shell.hook.ts +19 -0
  366. package/src/window/adopt.ts +57 -0
  367. package/src/window/hooks/close-guard.hook.ts +100 -0
  368. package/src/window/hooks/target-node.hook.ts +94 -0
  369. package/src/window/hooks/views-for.hook.ts +82 -0
  370. package/src/window/hooks/window.hook.ts +18 -0
  371. package/src/window/hooks/windows.hook.ts +40 -0
  372. package/src/window/host.tsx +347 -0
  373. package/src/window/hub.ts +156 -0
  374. package/src/window/index.ts +17 -0
  375. package/src/window/lifecycle/mount.ts +134 -0
  376. package/src/window/lifecycle/states.ts +23 -0
  377. package/src/window/placement.ts +84 -0
  378. 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
+ }