akanjs 3.0.2 → 3.1.0-rc.1

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 (395) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/base/baseEnv.ts +0 -4
  3. package/base/primitiveRegistry.ts +2 -2
  4. package/client/cookie.ts +5 -1
  5. package/client/csrLocation.ts +122 -0
  6. package/client/csrTypes.ts +36 -4
  7. package/client/device.ts +2 -1
  8. package/client/frameConfig.ts +78 -7
  9. package/client/index.ts +3 -0
  10. package/client/makePageProto.tsx +3 -2
  11. package/client/native/external-view.ts +1 -0
  12. package/client/route/RootLayoutDefinition.ts +7 -1
  13. package/client/route/RouteHead.ts +108 -0
  14. package/client/route/index.ts +1 -0
  15. package/client/router.ts +36 -23
  16. package/client/rscNavigation.ts +8 -2
  17. package/client/viewportMeta.ts +60 -0
  18. package/client/webManifest.ts +18 -0
  19. package/common/Logger.ts +7 -2
  20. package/common/PipelineNames.ts +31 -0
  21. package/common/PipelinePattern.ts +70 -0
  22. package/common/PipelinePlanSchema.ts +490 -0
  23. package/common/backoff.ts +14 -0
  24. package/common/index.ts +39 -0
  25. package/common/pipelinePlan.ts +259 -0
  26. package/common/routeConvention.ts +1 -0
  27. package/common/types.ts +17 -0
  28. package/constant/constantRegistry.ts +26 -6
  29. package/dictionary/base.dictionary.ts +12 -0
  30. package/dictionary/trans.ts +9 -1
  31. package/document/into.ts +5 -0
  32. package/fetch/client/fetchClient.ts +135 -31
  33. package/fetch/client/httpClient.ts +45 -0
  34. package/fetch/client/wsClient.ts +125 -16
  35. package/fetch/fetchType/buildFetch.type.ts +1 -0
  36. package/index.ts +243 -10
  37. package/package.json +1 -5
  38. package/server/akanApp.ts +5 -2
  39. package/server/akanServer.ts +44 -8
  40. package/server/artifact/builderRpc.ts +8 -3
  41. package/server/artifact/ipcTypes.ts +5 -2
  42. package/server/di/diLifecycle.ts +39 -3
  43. package/server/di/utils.ts +28 -1
  44. package/server/ed25519Key.ts +48 -0
  45. package/server/index.ts +1 -0
  46. package/server/machine/index.ts +2 -0
  47. package/server/machine/machineAccount.ts +27 -0
  48. package/server/machine/machineToken.ts +151 -0
  49. package/server/mcp/McpApps.ts +256 -0
  50. package/server/mcp/McpDispatcher.ts +31 -7
  51. package/server/mcp/McpRouter.ts +209 -46
  52. package/server/ops/opsToken.ts +3 -10
  53. package/server/resolver/database.resolver.ts +3 -0
  54. package/server/resolver/signal.resolver.ts +40 -3
  55. package/server/routeElementComposer.tsx +78 -2
  56. package/server/routeState.ts +6 -0
  57. package/server/routeTreeBuilder.ts +26 -9
  58. package/server/routing/apiRouter.ts +6 -3
  59. package/server/routing/roomReplay.ts +88 -0
  60. package/server/rscClient.tsx +53 -8
  61. package/server/rscWorker.tsx +141 -27
  62. package/server/rscWorkerHost.ts +18 -5
  63. package/server/sitemap.ts +14 -0
  64. package/server/ssrFromRscRenderer.tsx +12 -6
  65. package/server/ssrTypes.ts +3 -1
  66. package/server/systemPageDocument.tsx +38 -30
  67. package/server/types.tsx +2 -0
  68. package/server/webRouter.ts +74 -5
  69. package/service/adapt.ts +1 -1
  70. package/service/injectInfo.ts +9 -1
  71. package/service/ipcTypes.ts +2 -1
  72. package/service/predefinedAdaptor/database.adaptor.ts +1 -146
  73. package/service/predefinedAdaptor/queue.adaptor.ts +44 -6
  74. package/service/predefinedAdaptor/queueBackoff.ts +12 -0
  75. package/service/predefinedAdaptor/solidQueue.adaptor.ts +17 -13
  76. package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +44 -2
  77. package/service/predefinedAdaptor/sql/dialect/postgres.ts +3 -0
  78. package/service/predefinedAdaptor/sql/dialect/sqlite.ts +5 -2
  79. package/service/predefinedAdaptor/sql/search/fts5.ts +1 -1
  80. package/service/predefinedAdaptor/sql/types.ts +8 -6
  81. package/service/predefinedAdaptor/sql/values.ts +0 -23
  82. package/service/serve.ts +5 -1
  83. package/signal/agent.signal.ts +1 -1
  84. package/signal/base.signal.ts +2 -2
  85. package/signal/endpointIdempotency.ts +53 -0
  86. package/signal/internalArg.ts +14 -0
  87. package/signal/mcp/McpDocument.ts +38 -1
  88. package/signal/mcp/mcpProtocol.ts +18 -0
  89. package/signal/signalContext.ts +58 -30
  90. package/signal/signalRegistry.ts +14 -4
  91. package/signal/types.ts +18 -3
  92. package/store/action.ts +17 -19
  93. package/store/agent/StoreSurfaceSource.ts +1 -1
  94. package/store/agentic/StToolBuilder.ts +3 -0
  95. package/test/conformance.ts +9 -33
  96. package/types/base/baseEnv.d.ts +0 -4
  97. package/types/base/primitiveRegistry.d.ts +1 -1
  98. package/types/client/csrLocation.d.ts +32 -0
  99. package/types/client/csrTypes.d.ts +43 -4
  100. package/types/client/frameConfig.d.ts +14 -2
  101. package/types/client/index.d.ts +3 -0
  102. package/types/client/native/external-view.d.ts +1 -0
  103. package/types/client/route/RootLayoutDefinition.d.ts +2 -1
  104. package/types/client/route/RouteHead.d.ts +13 -0
  105. package/types/client/route/index.d.ts +1 -0
  106. package/types/client/router.d.ts +6 -0
  107. package/types/client/rscNavigation.d.ts +4 -0
  108. package/types/client/viewportMeta.d.ts +18 -0
  109. package/types/client/webManifest.d.ts +4 -0
  110. package/types/common/PipelineNames.d.ts +6 -0
  111. package/types/common/PipelinePattern.d.ts +14 -0
  112. package/types/common/PipelinePlanSchema.d.ts +9 -0
  113. package/types/common/backoff.d.ts +10 -0
  114. package/types/common/index.d.ts +5 -0
  115. package/types/common/pipelinePlan.d.ts +224 -0
  116. package/types/common/types.d.ts +16 -0
  117. package/types/constant/constantRegistry.d.ts +5 -2
  118. package/types/dictionary/base.dictionary.d.ts +1 -1
  119. package/types/dictionary/dictionary.d.ts +8 -8
  120. package/types/document/into.d.ts +9 -0
  121. package/types/fetch/client/fetchClient.d.ts +31 -4
  122. package/types/fetch/client/httpClient.d.ts +8 -0
  123. package/types/fetch/client/wsClient.d.ts +26 -2
  124. package/types/fetch/fetchType/buildFetch.type.d.ts +1 -0
  125. package/types/index.d.ts +230 -9
  126. package/types/server/akanServer.d.ts +16 -1
  127. package/types/server/artifact/builderRpc.d.ts +7 -2
  128. package/types/server/artifact/ipcTypes.d.ts +5 -1
  129. package/types/server/di/utils.d.ts +1 -0
  130. package/types/server/ed25519Key.d.ts +13 -0
  131. package/types/server/index.d.ts +1 -0
  132. package/types/server/machine/index.d.ts +2 -0
  133. package/types/server/machine/machineAccount.d.ts +5 -0
  134. package/types/server/machine/machineToken.d.ts +29 -0
  135. package/types/server/machine.d.ts +1 -0
  136. package/types/server/mcp/McpApps.d.ts +50 -0
  137. package/types/server/mcp/McpDispatcher.d.ts +4 -1
  138. package/types/server/mcp/McpRouter.d.ts +4 -0
  139. package/types/server/resolver/signal.resolver.d.ts +2 -1
  140. package/types/server/routeElementComposer.d.ts +24 -4
  141. package/types/server/routeState.d.ts +4 -1
  142. package/types/server/routing/roomReplay.d.ts +24 -0
  143. package/types/server/rscWorkerHost.d.ts +5 -2
  144. package/types/server/sitemap.d.ts +2 -0
  145. package/types/server/ssrFromRscRenderer.d.ts +3 -3
  146. package/types/server/ssrTypes.d.ts +4 -1
  147. package/types/server/systemPageDocument.d.ts +2 -0
  148. package/types/server/types.d.ts +4 -1
  149. package/types/server/webRouter.d.ts +3 -1
  150. package/types/service/adapt.d.ts +1 -1
  151. package/types/service/ipcTypes.d.ts +2 -0
  152. package/types/service/predefinedAdaptor/database.adaptor.d.ts +1 -24
  153. package/types/service/predefinedAdaptor/queue.adaptor.d.ts +10 -3
  154. package/types/service/predefinedAdaptor/queueBackoff.d.ts +4 -0
  155. package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +3 -3
  156. package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +6 -1
  157. package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +1 -0
  158. package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +1 -0
  159. package/types/service/predefinedAdaptor/sql/search/fts5.d.ts +1 -1
  160. package/types/service/predefinedAdaptor/sql/types.d.ts +9 -5
  161. package/types/service/predefinedAdaptor/sql/values.d.ts +0 -3
  162. package/types/service/serve.d.ts +3 -0
  163. package/types/signal/endpointIdempotency.d.ts +7 -0
  164. package/types/signal/internalArg.d.ts +10 -0
  165. package/types/signal/mcp/McpDocument.d.ts +8 -0
  166. package/types/signal/mcp/mcpProtocol.d.ts +17 -0
  167. package/types/signal/signalContext.d.ts +5 -3
  168. package/types/signal/signalRegistry.d.ts +4 -4
  169. package/types/signal/types.d.ts +21 -1
  170. package/types/store/agentic/StToolBuilder.d.ts +2 -0
  171. package/types/test/conformance.d.ts +7 -10
  172. package/types/ui/Agent/Chat.d.ts +5 -1
  173. package/types/ui/Agent/EmbedApproval.d.ts +1 -0
  174. package/types/ui/Agent/index.d.ts +3 -0
  175. package/types/ui/Agent/useKeyboardFrame.d.ts +2 -0
  176. package/types/ui/Agent/useScreenActions.d.ts +18 -0
  177. package/types/ui/BottomSheet.d.ts +1 -0
  178. package/types/ui/Constant/Doc.d.ts +11 -17
  179. package/types/ui/Constant/index.d.ts +7 -2
  180. package/types/ui/Constant/schemaDoc.d.ts +11 -0
  181. package/types/ui/Dialog/Modal.d.ts +6 -1
  182. package/types/ui/Dialog/index.d.ts +1 -1
  183. package/types/ui/Dialog/modalSurface.d.ts +12 -0
  184. package/types/ui/Layout/BottomInset.d.ts +1 -1
  185. package/types/ui/Layout/BottomTab.d.ts +11 -2
  186. package/types/ui/Layout/FrameSlotFallback.d.ts +9 -0
  187. package/types/ui/Layout/Navbar.d.ts +4 -1
  188. package/types/ui/Layout/TopInset.d.ts +1 -1
  189. package/types/ui/Layout/index.d.ts +4 -4
  190. package/types/ui/Link/Action.d.ts +5 -1
  191. package/types/ui/Link/Anchor.d.ts +5 -3
  192. package/types/ui/Link/activePath.d.ts +13 -0
  193. package/types/ui/Link/index.d.ts +1 -1
  194. package/types/ui/Modal.d.ts +6 -1
  195. package/types/ui/Model/EditModal.d.ts +6 -1
  196. package/types/ui/Model/New.d.ts +6 -1
  197. package/types/ui/Model/ViewEditModal.d.ts +6 -1
  198. package/types/ui/Model/ViewModal.d.ts +6 -1
  199. package/types/ui/Model/newFormOrigin.d.ts +7 -0
  200. package/types/ui/Portal.d.ts +3 -1
  201. package/types/ui/Reference/origin.d.ts +12 -0
  202. package/types/ui/Signal/Doc.d.ts +23 -18
  203. package/types/ui/Signal/Listener.d.ts +2 -6
  204. package/types/ui/Signal/Object.d.ts +6 -10
  205. package/types/ui/Signal/Response.d.ts +3 -6
  206. package/types/ui/Signal/RestApi.d.ts +11 -15
  207. package/types/ui/Signal/WebSocket.d.ts +11 -21
  208. package/types/ui/Signal/endpointEntries.d.ts +8 -0
  209. package/types/ui/Signal/index.d.ts +35 -12
  210. package/types/ui/Signal/signalText.d.ts +178 -0
  211. package/types/ui/System/CSR.d.ts +2 -2
  212. package/types/ui/System/Client.d.ts +4 -3
  213. package/types/ui/System/Common.d.ts +27 -6
  214. package/types/ui/System/SSR.d.ts +6 -6
  215. package/types/ui/Tooltip.d.ts +4 -2
  216. package/types/ui/index.d.ts +2 -1
  217. package/types/ui/overlayLayer.d.ts +6 -0
  218. package/types/ui/overlayPosition.d.ts +17 -0
  219. package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +14 -3
  220. package/types/vendor/@akanjs/native/packages/cli/src/commands/update.d.ts +1 -1
  221. package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +30 -5
  222. package/types/vendor/@akanjs/native/packages/cli/src/lib/compat.d.ts +8 -0
  223. package/types/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.d.ts +5 -0
  224. package/types/vendor/@akanjs/native/packages/cli/src/lib/distribution.d.ts +22 -0
  225. package/types/vendor/@akanjs/native/packages/cli/src/lib/project.d.ts +4 -0
  226. package/types/vendor/@akanjs/native/packages/cli/src/lib/publish.d.ts +16 -10
  227. package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +51 -7
  228. package/types/vendor/@akanjs/native/packages/cli/src/lib/vectors.d.ts +1 -1
  229. package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.d.ts +12 -4
  230. package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows.d.ts +5 -0
  231. package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +36 -0
  232. package/types/vendor/@akanjs/native/packages/desktop/src/dispatcher.d.ts +6 -0
  233. package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +2 -0
  234. package/types/vendor/@akanjs/native/packages/desktop/src/server.d.ts +11 -0
  235. package/types/vendor/@akanjs/native/plugins/external-view/src/desktop.d.ts +17 -0
  236. package/types/vendor/@akanjs/native/plugins/external-view/src/index.d.ts +132 -0
  237. package/types/vendor/@akanjs/native/plugins/external-view/src.d.ts +1 -0
  238. package/types/vendor/@akanjs/native/plugins/single-instance/src/socket.d.ts +1 -1
  239. package/types/vendor/@akanjs/native/plugins/updates/src/index.d.ts +8 -0
  240. package/types/vendor/@akanjs/native/plugins/window/src/desktop.d.ts +4 -1
  241. package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +49 -0
  242. package/types/vendor/use-agentic/AgentActivity.d.ts +3 -1
  243. package/types/vendor/use-agentic/AgenticSurface.d.ts +2 -2
  244. package/types/vendor/use-agentic/types.d.ts +2 -0
  245. package/types/webkit/CsrStack.d.ts +1 -1
  246. package/types/webkit/EmbeddedLayout.d.ts +10 -0
  247. package/types/webkit/McpAppAgent.d.ts +14 -0
  248. package/types/webkit/McpAppApprovals.d.ts +8 -0
  249. package/types/webkit/McpAppBridge.d.ts +101 -0
  250. package/types/webkit/McpAppView.d.ts +21 -0
  251. package/types/webkit/RenderLayer.d.ts +3 -1
  252. package/types/webkit/index.d.ts +1 -0
  253. package/types/webkit/useLocation.d.ts +1 -1
  254. package/types/webkit/useVisualViewportFrame.d.ts +13 -0
  255. package/ui/Agent/Chat.tsx +29 -10
  256. package/ui/Agent/Composer.tsx +2 -1
  257. package/ui/Agent/EmbedApproval.tsx +17 -0
  258. package/ui/Agent/RichInput.tsx +1 -1
  259. package/ui/Agent/index.ts +2 -0
  260. package/ui/Agent/useKeyboardFrame.ts +10 -0
  261. package/ui/Agent/useScreenActions.ts +45 -0
  262. package/ui/BottomSheet.tsx +82 -53
  263. package/ui/Constant/Doc.tsx +113 -60
  264. package/ui/Constant/index.ts +2 -2
  265. package/ui/Constant/schemaDoc.ts +86 -26
  266. package/ui/Dialog/LegacyModal.tsx +53 -52
  267. package/ui/Dialog/Modal.tsx +93 -49
  268. package/ui/Dialog/modalSurface.ts +61 -0
  269. package/ui/DragAction.tsx +1 -1
  270. package/ui/DraggableList.tsx +1 -1
  271. package/ui/Dropdown.tsx +4 -6
  272. package/ui/KeyboardAvoiding.tsx +1 -1
  273. package/ui/Layout/BottomInset.tsx +32 -16
  274. package/ui/Layout/BottomTab.tsx +42 -16
  275. package/ui/Layout/FrameSlotFallback.tsx +59 -0
  276. package/ui/Layout/Navbar.tsx +56 -15
  277. package/ui/Layout/Sider.tsx +1 -1
  278. package/ui/Layout/TopInset.tsx +22 -17
  279. package/ui/Link/Action.tsx +15 -5
  280. package/ui/Link/Anchor.tsx +25 -13
  281. package/ui/Link/activePath.ts +25 -0
  282. package/ui/Link/index.tsx +1 -1
  283. package/ui/Load/Pagination.tsx +1 -1
  284. package/ui/Load/Units.tsx +1 -1
  285. package/ui/Loading/ProgressBar.tsx +1 -1
  286. package/ui/Modal.tsx +9 -0
  287. package/ui/Model/EditModal.tsx +16 -1
  288. package/ui/Model/New.tsx +25 -2
  289. package/ui/Model/NewWrapper_Client.tsx +2 -0
  290. package/ui/Model/ViewEditModal.tsx +25 -10
  291. package/ui/Model/ViewModal.tsx +16 -1
  292. package/ui/Model/newFormOrigin.ts +45 -0
  293. package/ui/Popconfirm.tsx +5 -7
  294. package/ui/Portal.tsx +4 -7
  295. package/ui/Reference/origin.ts +31 -0
  296. package/ui/ScreenNavigator.tsx +1 -1
  297. package/ui/Select.tsx +14 -14
  298. package/ui/Signal/Arg.tsx +2 -2
  299. package/ui/Signal/Doc.tsx +125 -63
  300. package/ui/Signal/Endpoint.tsx +11 -10
  301. package/ui/Signal/Listener.tsx +7 -10
  302. package/ui/Signal/Object.tsx +7 -14
  303. package/ui/Signal/Response.tsx +24 -24
  304. package/ui/Signal/RestApi.tsx +63 -52
  305. package/ui/Signal/WebSocket.tsx +65 -72
  306. package/ui/Signal/endpointEntries.ts +25 -0
  307. package/ui/Signal/index.ts +23 -6
  308. package/ui/Signal/signalText.ts +59 -0
  309. package/ui/System/CSR.tsx +41 -9
  310. package/ui/System/Client.tsx +37 -5
  311. package/ui/System/Common.tsx +76 -32
  312. package/ui/System/SSR.tsx +73 -31
  313. package/ui/Toast.tsx +1 -1
  314. package/ui/Tooltip.tsx +84 -30
  315. package/ui/index.ts +11 -1
  316. package/ui/overlayLayer.ts +25 -2
  317. package/ui/overlayPosition.ts +90 -0
  318. package/ui/recipe/inputRecipe.ts +8 -1
  319. package/ui/styles.css +152 -0
  320. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +22 -2
  321. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeKernel.kt +37 -0
  322. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdateReports.kt +169 -0
  323. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdates.kt +110 -38
  324. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeVectors.kt +20 -0
  325. package/vendor/@akanjs/native/native/desktop/Cargo.lock +16 -16
  326. package/vendor/@akanjs/native/native/desktop/src/external.rs +651 -0
  327. package/vendor/@akanjs/native/native/desktop/src/json.rs +23 -0
  328. package/vendor/@akanjs/native/native/desktop/src/lib.rs +228 -5
  329. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeApp.swift +2 -1
  330. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeKernel.swift +47 -1
  331. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdateReports.swift +145 -0
  332. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdates.swift +112 -43
  333. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeVectors.swift +18 -0
  334. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeViewController.swift +24 -2
  335. package/vendor/@akanjs/native/packages/cli/src/api.ts +22 -6
  336. package/vendor/@akanjs/native/packages/cli/src/commands/build.ts +24 -8
  337. package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +11 -9
  338. package/vendor/@akanjs/native/packages/cli/src/config.ts +35 -7
  339. package/vendor/@akanjs/native/packages/cli/src/lib/compat.ts +2 -0
  340. package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +6 -4
  341. package/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.ts +11 -1
  342. package/vendor/@akanjs/native/packages/cli/src/lib/distribution.ts +73 -0
  343. package/vendor/@akanjs/native/packages/cli/src/lib/project.ts +15 -3
  344. package/vendor/@akanjs/native/packages/cli/src/lib/publish.ts +70 -23
  345. package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +159 -23
  346. package/vendor/@akanjs/native/packages/cli/src/lib/vectors.ts +2 -0
  347. package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +9 -4
  348. package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +1 -1
  349. package/vendor/@akanjs/native/packages/cli/src/platforms/desktop.ts +4 -2
  350. package/vendor/@akanjs/native/packages/cli/src/platforms/ios.ts +9 -4
  351. package/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.ts +60 -21
  352. package/vendor/@akanjs/native/packages/cli/src/platforms/windows.ts +14 -3
  353. package/vendor/@akanjs/native/packages/core/src/kernel.ts +49 -0
  354. package/vendor/@akanjs/native/packages/core/vectors/updates.json +31 -0
  355. package/vendor/@akanjs/native/packages/desktop/src/dispatcher.ts +13 -5
  356. package/vendor/@akanjs/native/packages/desktop/src/main.ts +3 -0
  357. package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +2 -0
  358. package/vendor/@akanjs/native/packages/desktop/src/server.ts +70 -6
  359. package/vendor/@akanjs/native/plugins/external-view/native-plugin.json +23 -0
  360. package/vendor/@akanjs/native/plugins/external-view/src/desktop.ts +321 -0
  361. package/vendor/@akanjs/native/plugins/external-view/src/index.ts +106 -0
  362. package/vendor/@akanjs/native/plugins/single-instance/src/desktop.ts +4 -0
  363. package/vendor/@akanjs/native/plugins/single-instance/src/socket.ts +12 -5
  364. package/vendor/@akanjs/native/plugins/updates/android/UpdatesPlugin.kt +133 -41
  365. package/vendor/@akanjs/native/plugins/updates/ios/UpdatesPlugin.swift +101 -36
  366. package/vendor/@akanjs/native/plugins/updates/native-plugin.json +4 -2
  367. package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +15 -1
  368. package/vendor/@akanjs/native/plugins/updates/src/index.ts +7 -1
  369. package/vendor/@akanjs/native/plugins/window/native-plugin.json +4 -0
  370. package/vendor/@akanjs/native/plugins/window/src/desktop.ts +68 -1
  371. package/vendor/@akanjs/native/plugins/window/src/index.ts +47 -0
  372. package/vendor/use-agentic/AgentActivity.tsx +4 -2
  373. package/vendor/use-agentic/AgenticSurface.ts +3 -3
  374. package/vendor/use-agentic/ToolRunner.ts +8 -1
  375. package/vendor/use-agentic/types.ts +2 -0
  376. package/webkit/CsrRouteTable.ts +9 -1
  377. package/webkit/CsrStack.ts +9 -2
  378. package/webkit/EmbeddedLayout.tsx +77 -0
  379. package/webkit/McpAppAgent.ts +138 -0
  380. package/webkit/McpAppApprovals.ts +56 -0
  381. package/webkit/McpAppBridge.ts +291 -0
  382. package/webkit/McpAppView.ts +258 -0
  383. package/webkit/RenderLayer.tsx +20 -5
  384. package/webkit/bootCsr.tsx +54 -5
  385. package/webkit/index.ts +1 -0
  386. package/webkit/useCsrValues.ts +16 -10
  387. package/webkit/useFrameRuntime.ts +10 -1
  388. package/webkit/useLocation.ts +4 -3
  389. package/webkit/useVisualViewportFrame.tsx +52 -0
  390. package/service/predefinedAdaptor/sql/driver/libsql.ts +0 -45
  391. package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +0 -20
  392. package/types/ui/Agent/useKeyboardInset.d.ts +0 -1
  393. package/types/ui/ServerPortal.d.ts +0 -15
  394. package/ui/Agent/useKeyboardInset.ts +0 -19
  395. package/ui/ServerPortal.tsx +0 -49
@@ -11,17 +11,26 @@ import {
11
11
  type ConstantCls,
12
12
  type ConstantField,
13
13
  type ConstantModel,
14
+ type ConstantOriginKind,
14
15
  ConstantRegistry,
15
16
  type TextFieldRole,
16
17
  } from "akanjs/constant";
18
+ import { ownerOf, ownerOrderOf } from "../Reference/origin";
17
19
 
18
20
  export const databaseModelVariants = ["input", "object", "full", "light", "insight"] as const;
19
21
  export type DatabaseModelVariant = (typeof databaseModelVariants)[number];
20
22
 
23
+ /**
24
+ * `undefined` is "every registered one" and `[]` is "none". Once any option narrows the scope, scalars default to
25
+ * the ones the shown models embed and enums to the ones the shown models and scalars use.
26
+ */
21
27
  export interface ConstantSchemaOptions {
22
28
  models?: string[];
23
29
  scalars?: string[];
24
30
  enums?: string[];
31
+ include?: string[];
32
+ exclude?: string[];
33
+ libs?: string[];
25
34
  }
26
35
 
27
36
  export interface ConstantSchemaDoc {
@@ -34,6 +43,7 @@ export interface ConstantSchemaDoc {
34
43
  export interface DatabaseSchema {
35
44
  kind: "database";
36
45
  refName: string;
46
+ origin: string[];
37
47
  modelName: string;
38
48
  variants: Record<DatabaseModelVariant, ModelVariantSchema>;
39
49
  }
@@ -41,6 +51,7 @@ export interface DatabaseSchema {
41
51
  export interface ScalarSchema {
42
52
  kind: "scalar";
43
53
  refName: string;
54
+ origin: string[];
44
55
  modelName: string;
45
56
  modelRef: ConstantCls;
46
57
  fields: FieldSchema[];
@@ -57,6 +68,7 @@ export interface ModelVariantSchema {
57
68
  export interface EnumSchema {
58
69
  key: string;
59
70
  refName: string;
71
+ origin: string[];
60
72
  typeName: string;
61
73
  values: (string | number)[];
62
74
  enumRef: EnumInstance;
@@ -105,33 +117,80 @@ export interface FieldSchema {
105
117
  }
106
118
 
107
119
  export const getConstantSchemaDoc = (options: ConstantSchemaOptions = {}): ConstantSchemaDoc => {
108
- const databases = getSelectedEntries(ConstantRegistry.database, options.models).map(([refName, model]) =>
109
- buildDatabaseSchema(refName, model),
110
- );
111
- const scalars = getSelectedEntries(ConstantRegistry.scalar, options.scalars).map(([refName, scalar]) => {
112
- const modelRef = scalar.model;
113
- return {
114
- kind: "scalar" as const,
115
- refName,
116
- modelName: getModelName(modelRef, refName),
117
- modelRef,
118
- fields: getFields(modelRef, "scalar"),
119
- };
120
- });
121
- const selectedEnums = getSelectedEntries(ConstantRegistry.enum, options.enums);
120
+ const { models, scalars: scalarKeys, enums: enumKeys, include, exclude, libs } = options;
121
+ const isScoped = [models, scalarKeys, enumKeys, include, exclude, libs].some((option) => option !== undefined);
122
+ const keeps = (kind: ConstantOriginKind) => (key: string) =>
123
+ !exclude?.includes(key) && (!libs || libs.includes(ownerOf(ConstantRegistry.getOrigin(kind, key)) ?? ""));
124
+ const isRoot = (key: string) => keeps("database")(key) && (!include || include.includes(key));
125
+ const databases = selectKeys(ConstantRegistry.database, models)
126
+ .filter(isRoot)
127
+ .map((refName) => buildDatabaseSchema(refName, ConstantRegistry.getDatabase(refName)));
128
+ const scalars = (
129
+ scalarKeys !== undefined
130
+ ? selectKeys(ConstantRegistry.scalar, scalarKeys).filter(keeps("scalar"))
131
+ : isScoped
132
+ ? collectEmbeddedScalars(
133
+ databases,
134
+ include ? selectKeys(ConstantRegistry.scalar, include).filter(keeps("scalar")) : [],
135
+ keeps("scalar"),
136
+ )
137
+ : selectKeys(ConstantRegistry.scalar)
138
+ ).map(buildScalarSchema);
122
139
  const enumUsages = collectEnumUsages(databases, scalars);
123
- const enums = selectedEnums.map(([key, enumRef]) => ({
140
+ const enums = selectKeys(ConstantRegistry.enum, enumKeys)
141
+ .filter(keeps("enum"))
142
+ .map((key) => buildEnumSchema(key, enumUsages))
143
+ .filter((enumSchema) => enumKeys !== undefined || !isScoped || enumSchema.usedBy.length);
144
+ const relations = collectRelations(databases, scalars);
145
+ return { databases, scalars, enums, relations };
146
+ };
147
+
148
+ const buildScalarSchema = (refName: string): ScalarSchema => {
149
+ const modelRef = ConstantRegistry.getScalar(refName).model;
150
+ return {
151
+ kind: "scalar",
152
+ refName,
153
+ origin: ConstantRegistry.getOrigin("scalar", refName),
154
+ modelName: getModelName(modelRef, refName),
155
+ modelRef,
156
+ fields: getFields(modelRef, "scalar"),
157
+ };
158
+ };
159
+
160
+ const buildEnumSchema = (key: string, enumUsages: Map<EnumInstance, EnumUsage[]>): EnumSchema => {
161
+ const enumRef = ConstantRegistry.enum.get(key) as EnumInstance;
162
+ return {
124
163
  key,
125
164
  refName: enumRef.refName,
165
+ origin: ConstantRegistry.getOrigin("enum", key),
126
166
  typeName: PrimitiveRegistry.getName(enumRef.type as typeof PrimitiveScalar),
127
167
  values: [...enumRef.values] as (string | number)[],
128
168
  enumRef,
129
169
  usedBy: enumUsages.get(enumRef) ?? [],
130
- }));
131
- const relations = collectRelations(databases, scalars);
132
- return { databases, scalars, enums, relations };
170
+ };
171
+ };
172
+
173
+ const collectEmbeddedScalars = (
174
+ databases: DatabaseSchema[],
175
+ rootScalars: string[],
176
+ isKept: (key: string) => boolean,
177
+ ) => {
178
+ const found = new Set(rootScalars);
179
+ const visit = (fields: FieldSchema[]) => {
180
+ for (const field of fields) {
181
+ const refName = field.typeRefName;
182
+ if (!refName || found.has(refName) || !isKept(refName) || !ConstantRegistry.scalar.has(refName)) continue;
183
+ found.add(refName);
184
+ visit(getFields(ConstantRegistry.getScalar(refName).model, "scalar"));
185
+ }
186
+ };
187
+ for (const database of databases) for (const variant of Object.values(database.variants)) visit(variant.fields);
188
+ for (const refName of rootScalars) visit(getFields(ConstantRegistry.getScalar(refName).model, "scalar"));
189
+ return [...found].sort((a, b) => a.localeCompare(b));
133
190
  };
134
191
 
192
+ export const getConstantOwnerOrder = () => ownerOrderOf([...ConstantRegistry.origin.values()]);
193
+
135
194
  export const getDefaultVariant = (database: DatabaseSchema): ModelVariantSchema => database.variants.full;
136
195
 
137
196
  export const getVariantTitle = (variant: DatabaseModelVariant | "scalar") => {
@@ -155,7 +214,13 @@ const buildDatabaseSchema = (refName: string, model: ConstantModel): DatabaseSch
155
214
  ];
156
215
  }),
157
216
  ) as Record<DatabaseModelVariant, ModelVariantSchema>;
158
- return { kind: "database", refName, modelName: ConstantRegistry.getModelName(model.full), variants };
217
+ return {
218
+ kind: "database",
219
+ refName,
220
+ origin: ConstantRegistry.getOrigin("database", refName),
221
+ modelName: ConstantRegistry.getModelName(model.full),
222
+ variants,
223
+ };
159
224
  };
160
225
 
161
226
  const getFields = (modelRef: ConstantCls, variant: DatabaseModelVariant | "scalar"): FieldSchema[] =>
@@ -265,13 +330,8 @@ const getConstraints = (props: ReturnType<ConstantField["getProps"]>) =>
265
330
  props.accumulate ? "accumulate" : null,
266
331
  ].filter((constraint): constraint is string => !!constraint);
267
332
 
268
- const getSelectedEntries = <Value>(map: Map<string, Value>, selected?: string[]): [string, Value][] => {
269
- if (!selected?.length) return [...map.entries()].sort(([a], [b]) => a.localeCompare(b));
270
- return selected.flatMap((key) => {
271
- const value = map.get(key);
272
- return value ? ([[key, value]] as [string, Value][]) : [];
273
- });
274
- };
333
+ const selectKeys = (map: Map<string, unknown>, selected?: string[]) =>
334
+ selected ? selected.filter((key) => map.has(key)) : [...map.keys()].sort((a, b) => a.localeCompare(b));
275
335
 
276
336
  const collectEnumUsages = (databases: DatabaseSchema[], scalars: ScalarSchema[]) => {
277
337
  const usages = new Map<EnumInstance, EnumUsage[]>();
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import { useDrag } from "@use-gesture/react";
3
3
  import { cn, usePage } from "akanjs/client";
4
- import { animated } from "akanjs/ui";
5
4
  import { useBodyScrollLock, useEscapeKey } from "akanjs/webkit";
6
5
  import { type ReactNode, useCallback, useContext, useEffect, useId, useRef, useState } from "react";
7
6
  import { createPortal } from "react-dom";
8
7
  import { BiX } from "react-icons/bi";
9
8
  import { config, useSpring } from "react-spring";
9
+ import { animated } from "../animated";
10
10
  import { buttonRecipe } from "../Button";
11
- import { useOverlayLayerProps } from "../overlayLayer";
11
+ import { OverlayPortalProvider, overlayZ, useOverlayLayerProps, useOverlayPortal } from "../overlayLayer";
12
12
 
13
13
  import { DialogContext } from "./Provider";
14
14
 
@@ -38,7 +38,8 @@ export const LegacyModal = ({ className, bodyClassName, confirmClose, children,
38
38
  const contentId = useId();
39
39
  const overlayLayerProps = useOverlayLayerProps();
40
40
  const [{ translate }, api] = useSpring(() => ({ translate: 1 }));
41
- const [portalElement, setPortalElement] = useState<HTMLElement | null>(null);
41
+ const portalElement = useOverlayPortal();
42
+ const [root, setRoot] = useState<HTMLDivElement | null>(null);
42
43
  const [isMounted, setIsMounted] = useState(open);
43
44
  const [showBackground, setShowBackground] = useState(false);
44
45
 
@@ -111,11 +112,6 @@ export const LegacyModal = ({ className, bodyClassName, confirmClose, children,
111
112
  return `${t * 100}%`;
112
113
  });
113
114
 
114
- useEffect(() => {
115
- if (typeof document === "undefined") return;
116
- setPortalElement(document.body);
117
- }, []);
118
-
119
115
  useEffect(() => {
120
116
  if (open) {
121
117
  void openModal();
@@ -171,65 +167,70 @@ export const LegacyModal = ({ className, bodyClassName, confirmClose, children,
171
167
  <>
172
168
  <div
173
169
  {...overlayLayerProps}
174
- className={cn("fixed inset-0 z-10", showBackground && "animate-fadeIn bg-black/50 backdrop-blur-sm")}
170
+ className={cn("fixed inset-0", showBackground && "animate-fadeIn bg-black/50 backdrop-blur-sm")}
171
+ style={{ zIndex: overlayZ.modal }}
175
172
  />
176
173
  <div
177
174
  {...overlayLayerProps}
178
- className="fixed inset-0 z-10 flex items-center justify-center p-4"
175
+ ref={setRoot}
176
+ className="fixed inset-0 flex items-center justify-center p-4"
177
+ style={{ zIndex: overlayZ.modal }}
179
178
  onClick={(event) => {
180
179
  if (event.target !== event.currentTarget) return;
181
180
  requestClose();
182
181
  }}
183
182
  >
184
- <animated.div
185
- ref={ref}
186
- style={{ translateY, opacity }}
187
-
188
- className={cn(
189
- "relative flex max-h-full w-full max-w-2xl flex-col overflow-hidden rounded-box border border-border bg-card text-card-foreground shadow-2xl shadow-black/25 outline-none",
190
- className,
191
- )}
192
- role="dialog"
193
- aria-modal="true"
194
- aria-labelledby={title ? titleId : undefined}
195
- aria-describedby={contentId}
196
- tabIndex={-1}
197
- >
183
+ <OverlayPortalProvider value={root}>
198
184
  <animated.div
199
- {...bind()}
185
+ ref={ref}
186
+ style={{ translateY, opacity }}
187
+
200
188
  className={cn(
201
- "flex shrink-0 touch-pan-y flex-col",
202
- title && "border-border/70 border-b bg-card/80 backdrop-blur-sm",
189
+ "relative flex max-h-full w-full max-w-2xl flex-col overflow-hidden rounded-box border border-border bg-card text-card-foreground shadow-2xl shadow-black/25 outline-none",
190
+ className,
203
191
  )}
192
+ role="dialog"
193
+ aria-modal="true"
194
+ aria-labelledby={title ? titleId : undefined}
195
+ aria-describedby={contentId}
196
+ tabIndex={-1}
204
197
  >
205
- <div className="flex justify-center pt-2 md:hidden">
206
- <div className="h-1 w-10 rounded-full bg-foreground/15" />
207
- </div>
208
- <div className="flex items-start gap-3 px-5 pt-4 pb-3">
209
- <div className="min-w-0 flex-1 font-semibold text-lg leading-snug" id={titleId}>
210
- {title}
198
+ <animated.div
199
+ {...bind()}
200
+ className={cn(
201
+ "flex shrink-0 touch-pan-y flex-col",
202
+ title && "border-border/70 border-b bg-card/80 backdrop-blur-sm",
203
+ )}
204
+ >
205
+ <div className="flex justify-center pt-2 md:hidden">
206
+ <div className="h-1 w-10 rounded-full bg-foreground/15" />
207
+ </div>
208
+ <div className="flex items-start gap-3 px-5 pt-4 pb-3">
209
+ <div className="min-w-0 flex-1 font-semibold text-lg leading-snug" id={titleId}>
210
+ {title}
211
+ </div>
212
+ <button
213
+ aria-label="Close"
214
+ className={buttonRecipe(
215
+ { variant: "ghost", size: "icon" },
216
+ "-mt-1 -mr-2 size-8 shrink-0 rounded-full text-foreground/45 hover:text-foreground",
217
+ )}
218
+ onClick={() => requestClose()}
219
+ type="button"
220
+ >
221
+ <BiX className="text-2xl" />
222
+ </button>
211
223
  </div>
212
- <button
213
- aria-label="Close"
214
- className={buttonRecipe(
215
- { variant: "ghost", size: "icon" },
216
- "-mt-1 -mr-2 size-8 shrink-0 rounded-full text-foreground/45 hover:text-foreground",
217
- )}
218
- onClick={() => requestClose()}
219
- type="button"
220
- >
221
- <BiX className="text-2xl" />
222
- </button>
224
+ </animated.div>
225
+ <div
226
+ className={cn("min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-5 pt-4 pb-5", bodyClassName)}
227
+ id={contentId}
228
+ >
229
+ {children}
223
230
  </div>
231
+ {action ? <div className="shrink-0 border-border/70 border-t bg-muted/30 px-5 py-4">{action}</div> : null}
224
232
  </animated.div>
225
- <div
226
- className={cn("min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-5 pt-4 pb-5", bodyClassName)}
227
- id={contentId}
228
- >
229
- {children}
230
- </div>
231
- {action ? <div className="shrink-0 border-border/70 border-t bg-muted/30 px-5 py-4">{action}</div> : null}
232
- </animated.div>
233
+ </OverlayPortalProvider>
233
234
  </div>
234
235
  </>,
235
236
  portalElement,
@@ -1,14 +1,18 @@
1
1
  "use client";
2
+ import { useDrag } from "@use-gesture/react";
2
3
  import { cn, usePage } from "akanjs/client";
3
4
  import { useBodyScrollLock, useEscapeKey } from "akanjs/webkit";
4
5
  import { type ReactNode, useCallback, useContext, useEffect, useId, useRef, useState } from "react";
5
6
  import { createPortal } from "react-dom";
6
7
  import { BiX } from "react-icons/bi";
7
8
  import { buttonRecipe } from "../Button";
8
- import { useOverlayLayerProps } from "../overlayLayer";
9
+ import { OverlayPortalProvider, overlayZ, useOverlayLayerProps, useOverlayPortal } from "../overlayLayer";
9
10
 
11
+ import { isSheetNow, type ModalPlacement, type ModalPresentation, modalSurfaceOf } from "./modalSurface";
10
12
  import { DialogContext } from "./Provider";
11
13
 
14
+ const DISMISS_DRAG_PX = 120;
15
+
12
16
  export interface ModalProps {
13
17
  className?: string;
14
18
  bodyClassName?: string;
@@ -17,8 +21,21 @@ export interface ModalProps {
17
21
  closeButton?: ReactNode | false;
18
22
  children?: ReactNode;
19
23
  onCancel?: () => void;
24
+ /** `auto` is a full-screen sheet below `md`, which a drag down on its handle or title dismisses. */
25
+ presentation?: ModalPresentation;
26
+ /** `right` is a full-height side sheet from `md` up. */
27
+ placement?: ModalPlacement;
20
28
  }
21
- export const Modal = ({ className, bodyClassName, confirmClose, closeButton, children, onCancel }: ModalProps) => {
29
+ export const Modal = ({
30
+ className,
31
+ bodyClassName,
32
+ confirmClose,
33
+ closeButton,
34
+ children,
35
+ onCancel,
36
+ presentation = "dialog",
37
+ placement = "center",
38
+ }: ModalProps) => {
22
39
  const { open, setOpen, registerDismiss, title, action } = useContext(DialogContext);
23
40
  const { l } = usePage();
24
41
  const ref = useRef<HTMLDivElement>(null);
@@ -26,8 +43,10 @@ export const Modal = ({ className, bodyClassName, confirmClose, closeButton, chi
26
43
  const titleId = useId();
27
44
  const contentId = useId();
28
45
  const overlayLayerProps = useOverlayLayerProps();
29
-
30
- const [portalElement, setPortalElement] = useState<HTMLElement | null>(null);
46
+ const portalElement = useOverlayPortal();
47
+ const [root, setRoot] = useState<HTMLDivElement | null>(null);
48
+ const [dragY, setDragY] = useState(0);
49
+ const surface = modalSurfaceOf(presentation, placement);
31
50
 
32
51
  const requestClose = useCallback(() => {
33
52
  if (confirmClose && !window.confirm(l("base.confirmClose"))) return;
@@ -35,10 +54,19 @@ export const Modal = ({ className, bodyClassName, confirmClose, closeButton, chi
35
54
  onCancel?.();
36
55
  }, [confirmClose, l, onCancel, setOpen]);
37
56
 
38
- useEffect(() => {
39
- if (typeof document === "undefined") return;
40
- setPortalElement(document.body);
41
- }, []);
57
+ const bindDismissDrag = useDrag(
58
+ ({ down, movement: [, my], velocity: [, vy], direction: [, dy] }) => {
59
+ if (!isSheetNow(presentation, placement)) return;
60
+ if (down) {
61
+ setDragY(Math.max(0, my));
62
+ return;
63
+ }
64
+ setDragY(0);
65
+ if (my > DISMISS_DRAG_PX || (vy > 0.5 && dy > 0)) requestClose();
66
+ },
67
+ { axis: "y", filterTaps: true },
68
+ );
69
+ const dragProps = presentation === "dialog" ? {} : bindDismissDrag();
42
70
 
43
71
  useBodyScrollLock(open);
44
72
  useEscapeKey(open, requestClose);
@@ -69,55 +97,71 @@ export const Modal = ({ className, bodyClassName, confirmClose, closeButton, chi
69
97
  return createPortal(
70
98
  <div
71
99
  {...overlayLayerProps}
72
- className="fixed inset-0 z-10 flex items-center justify-center bg-black/40 p-4"
100
+ ref={setRoot}
101
+ className={cn("fixed inset-0 flex bg-black/40", surface.root)}
102
+ style={{ zIndex: overlayZ.modal }}
73
103
  onClick={(event) => {
74
104
  if (event.target !== event.currentTarget) return;
75
105
  requestClose();
76
106
  }}
77
107
  >
78
- <div
79
- ref={ref}
80
-
81
- className={cn(
82
- "relative flex max-h-full w-full max-w-2xl flex-col overflow-hidden rounded-box border border-border bg-card text-card-foreground shadow-lg outline-none",
83
- className,
84
- )}
85
- role="dialog"
86
- aria-modal="true"
87
- aria-labelledby={title ? titleId : undefined}
88
- aria-describedby={contentId}
89
- tabIndex={-1}
90
- >
91
- {/* The dismissal is on the slot, not on the button inside it, so a replacement needs no wiring — a
108
+ <OverlayPortalProvider value={root}>
109
+ <div
110
+ ref={ref}
111
+
112
+ className={cn(
113
+ "relative flex w-full flex-col overflow-hidden bg-card text-card-foreground shadow-lg outline-none",
114
+ surface.panel,
115
+ dragY === 0 && "transition-transform",
116
+ className,
117
+ )}
118
+ style={dragY ? { transform: `translateY(${dragY}px)` } : undefined}
119
+ role="dialog"
120
+ aria-modal="true"
121
+ aria-labelledby={title ? titleId : undefined}
122
+ aria-describedby={contentId}
123
+ tabIndex={-1}
124
+ >
125
+ {/* The dismissal is on the slot, not on the button inside it, so a replacement needs no wiring — a
92
126
  click on whatever the caller put here bubbles to exactly one handler. */}
93
- {closeButton === false ? null : (
94
- <div className="absolute top-3 right-3 z-10" onClick={() => requestClose()}>
95
- {closeButton ?? (
96
- <button
97
- aria-label="Close"
98
- className={buttonRecipe({ variant: "ghost", size: "icon" }, "size-8")}
99
- type="button"
100
- >
101
- <BiX className="text-xl" />
102
- </button>
103
- )}
104
- </div>
105
- )}
106
- {title ? (
107
- <div
108
- className="shrink-0 border-border border-b py-3.5 pr-14 pl-5 font-semibold text-base leading-snug"
109
- id={titleId}
110
- >
111
- {title}
127
+ {closeButton === false ? null : (
128
+ <div className={cn("absolute right-3 z-10", surface.close)} onClick={() => requestClose()}>
129
+ {closeButton ?? (
130
+ <button
131
+ aria-label="Close"
132
+ className={buttonRecipe({ variant: "ghost", size: "icon" }, "size-8")}
133
+ type="button"
134
+ >
135
+ <BiX className="text-xl" />
136
+ </button>
137
+ )}
138
+ </div>
139
+ )}
140
+ {presentation === "dialog" ? null : (
141
+ <div {...dragProps} className={cn("shrink-0 touch-none justify-center pt-2", surface.handle)}>
142
+ <div className="h-1 w-10 rounded-full bg-foreground/15" />
143
+ </div>
144
+ )}
145
+ {title ? (
146
+ <div
147
+ {...dragProps}
148
+ className={cn(
149
+ "shrink-0 border-border border-b py-3.5 pr-14 pl-5 font-semibold text-base leading-snug",
150
+ presentation !== "dialog" && "touch-none",
151
+ )}
152
+ id={titleId}
153
+ >
154
+ {title}
155
+ </div>
156
+ ) : null}
157
+ <div className={cn("min-h-0 flex-1 overflow-y-auto px-5 py-4", bodyClassName)} id={contentId}>
158
+ {children}
112
159
  </div>
113
- ) : null}
114
- <div className={cn("min-h-0 flex-1 overflow-y-auto px-5 py-4", bodyClassName)} id={contentId}>
115
- {children}
160
+ {action ? (
161
+ <div className="flex shrink-0 justify-end gap-2 border-border border-t px-5 py-3">{action}</div>
162
+ ) : null}
116
163
  </div>
117
- {action ? (
118
- <div className="flex shrink-0 justify-end gap-2 border-border border-t px-5 py-3">{action}</div>
119
- ) : null}
120
- </div>
164
+ </OverlayPortalProvider>
121
165
  </div>,
122
166
  portalElement,
123
167
  );
@@ -0,0 +1,61 @@
1
+ /** How the modal shows on a phone: a centred dialog, a full-screen sheet, or a sheet below `md` and a dialog above. */
2
+ export type ModalPresentation = "dialog" | "sheet" | "auto";
3
+ /** Where the modal sits from `md` up: centred, or a full-height sheet on the right edge. */
4
+ export type ModalPlacement = "center" | "right";
5
+
6
+ interface SurfaceClassNames {
7
+ root: string;
8
+ panel: string;
9
+ close: string;
10
+ handle: string;
11
+ }
12
+
13
+ const presentationClassNames: { [presentation in ModalPresentation]: SurfaceClassNames } = {
14
+ dialog: {
15
+ root: "items-center justify-center p-4",
16
+ panel: "max-h-full max-w-2xl rounded-box border border-border",
17
+ close: "top-3",
18
+ handle: "hidden",
19
+ },
20
+ sheet: {
21
+ root: "items-stretch justify-stretch p-0",
22
+ panel:
23
+ "h-full max-h-full max-w-none rounded-none border-0 pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]",
24
+ close: "top-[calc(env(safe-area-inset-top)+0.75rem)]",
25
+ handle: "flex",
26
+ },
27
+ auto: {
28
+ root: "items-stretch p-0 md:items-center md:justify-center md:p-4",
29
+ panel:
30
+ "h-full max-h-full rounded-none border-0 pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)] md:h-auto md:max-w-2xl md:rounded-box md:border md:border-border md:pt-0 md:pb-0",
31
+ close: "top-[calc(env(safe-area-inset-top)+0.75rem)] md:top-3",
32
+ handle: "flex md:hidden",
33
+ },
34
+ } as const;
35
+
36
+ const placementClassNames: { [placement in ModalPlacement]: Pick<SurfaceClassNames, "root" | "panel"> } = {
37
+ center: { root: "", panel: "" },
38
+ right: {
39
+ root: "md:items-stretch md:justify-end md:p-0",
40
+ panel: "md:h-full md:max-h-full md:max-w-md md:rounded-none md:border-0 md:border-border md:border-l",
41
+ },
42
+ } as const;
43
+
44
+ export const modalSurfaceOf = (presentation: ModalPresentation, placement: ModalPlacement) => {
45
+ const shape = presentationClassNames[presentation];
46
+ const side = placementClassNames[placement];
47
+ return {
48
+ root: [shape.root, side.root],
49
+ panel: [shape.panel, side.panel],
50
+ close: shape.close,
51
+ handle: shape.handle,
52
+ };
53
+ };
54
+
55
+ /** Whether a drag down dismisses: only while the modal is drawn as a sheet at the current width. */
56
+ export const isSheetNow = (presentation: ModalPresentation, placement: ModalPlacement) => {
57
+ if (presentation === "dialog") return false;
58
+ const wide = typeof window !== "undefined" && window.matchMedia("(min-width: 48rem)").matches;
59
+ if (!wide) return true;
60
+ return presentation === "sheet" && placement === "center";
61
+ };
package/ui/DragAction.tsx CHANGED
@@ -2,10 +2,10 @@
2
2
  import { useGesture } from "@use-gesture/react";
3
3
  import type { ReactDOMAttributes } from "@use-gesture/react/dist/declarations/src/types";
4
4
  import { cn } from "akanjs/client";
5
- import { animated } from "akanjs/ui";
6
5
  import { type ReactNode, useContext, useRef } from "react";
7
6
  import { SpringValue, useSpring } from "react-spring";
8
7
  import { sharedContext } from "../client/sharedContext";
8
+ import { animated } from "./animated";
9
9
 
10
10
  interface DragActionContextType {
11
11
  bind: () => ReactDOMAttributes;
@@ -4,12 +4,12 @@ import { useGesture } from "@use-gesture/react";
4
4
  import { cn } from "akanjs/client";
5
5
  import { clamp } from "akanjs/common";
6
6
  import { useFieldTool } from "akanjs/store";
7
- import { animated } from "akanjs/ui";
8
7
  import { type ReactElement, type ReactNode, useContext, useRef } from "react";
9
8
  import { BiTrash } from "react-icons/bi";
10
9
  import { MdDragIndicator } from "react-icons/md";
11
10
  import { sharedContext } from "../client/sharedContext";
12
11
  import { agentAttrs } from "./agentAttrs";
12
+ import { animated } from "./animated";
13
13
  import { buttonRecipe } from "./Button";
14
14
  import { useUiRecipe } from "./UiOverride";
15
15
 
package/ui/Dropdown.tsx CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  OverlayOwnerProvider,
13
13
  overlayZ,
14
14
  useOverlayLayerProps,
15
+ useOverlayPortal,
15
16
  useOverlayScope,
16
17
  } from "./overlayLayer";
17
18
  import { useOverlayPosition } from "./overlayPosition";
@@ -49,8 +50,7 @@ export const DefaultDropdown = ({
49
50
  namespace,
50
51
  }: DropdownProps) => {
51
52
  const [opened, setOpened] = useState(false);
52
-
53
- const [portal, setPortal] = useState<HTMLElement | null>(null);
53
+ const portal = useOverlayPortal();
54
54
  const ref = useRef<HTMLDivElement>(null);
55
55
  const menuRef = useRef<HTMLUListElement>(null);
56
56
  const scope = useOverlayScope(useId());
@@ -75,9 +75,6 @@ export const DefaultDropdown = ({
75
75
  });
76
76
 
77
77
  const toggle = opened ? closeDropdown : openDropdown;
78
- useEffect(() => {
79
- setPortal(document.body);
80
- }, []);
81
78
  useEffect(() => {
82
79
  if (!opened) return;
83
80
  const onMouseDown = (e: MouseEvent) => {
@@ -104,7 +101,8 @@ export const DefaultDropdown = ({
104
101
  left: position?.left ?? 0,
105
102
  visibility: position ? undefined : "hidden",
106
103
  }}
107
- onClick={(e) => {
104
+
105
+ onClickCapture={(e) => {
108
106
 
109
107
  if (isOwnOverlayClick(e.target, scope)) return;
110
108
  if (e.target instanceof Element && e.target.closest(keepOpenSelector)) return;
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { useCsr } from "akanjs/client";
3
3
  import { st } from "akanjs/store";
4
- import { animated } from "akanjs/ui";
5
4
  import { type ReactNode, useEffect, useRef } from "react";
6
5
  import { useSpring } from "react-spring";
6
+ import { animated } from "./animated";
7
7
 
8
8
  interface KeyboardAvoidingProps {
9
9
  children: ReactNode;