@object-ui/app-shell 6.2.3 → 7.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 (486) hide show
  1. package/CHANGELOG.md +1229 -0
  2. package/README.md +292 -0
  3. package/dist/assistant/assistantBus.d.ts +72 -0
  4. package/dist/assistant/assistantBus.js +133 -0
  5. package/dist/chrome/CommandPalette.d.ts +1 -1
  6. package/dist/chrome/CommandPalette.js +26 -22
  7. package/dist/chrome/ConditionalAuthWrapper.d.ts +1 -1
  8. package/dist/chrome/ConsoleToaster.d.ts +1 -1
  9. package/dist/chrome/ConsoleToaster.js +3 -1
  10. package/dist/chrome/ErrorBoundary.d.ts +1 -1
  11. package/dist/chrome/KeyboardShortcutsDialog.d.ts +1 -1
  12. package/dist/chrome/KeyboardShortcutsDialog.js +16 -5
  13. package/dist/chrome/LoadingScreen.d.ts +1 -1
  14. package/dist/chrome/LoadingScreen.js +22 -26
  15. package/dist/chrome/RouteFader.d.ts +1 -1
  16. package/dist/chrome/ThemeProvider.d.ts +1 -1
  17. package/dist/components/ManagedByBadge.d.ts +1 -1
  18. package/dist/console/AppContent.d.ts +1 -1
  19. package/dist/console/AppContent.js +184 -39
  20. package/dist/console/ConsoleShell.d.ts +7 -7
  21. package/dist/console/ConsoleShell.js +32 -3
  22. package/dist/console/ai/AiChatPage.d.ts +88 -1
  23. package/dist/console/ai/AiChatPage.js +747 -66
  24. package/dist/console/ai/ConversationsSidebar.d.ts +26 -1
  25. package/dist/console/ai/ConversationsSidebar.js +149 -34
  26. package/dist/console/ai/LiveCanvas.d.ts +28 -0
  27. package/dist/console/ai/LiveCanvas.js +80 -0
  28. package/dist/console/ai/reconcileTurn.d.ts +8 -0
  29. package/dist/console/ai/reconcileTurn.js +20 -0
  30. package/dist/console/auth/AuthPageLayout.d.ts +1 -1
  31. package/dist/console/auth/ForgotPasswordPage.d.ts +1 -1
  32. package/dist/console/auth/LoginPage.d.ts +1 -1
  33. package/dist/console/auth/RegisterPage.d.ts +1 -1
  34. package/dist/console/auth/RegisterPage.js +23 -3
  35. package/dist/console/cloud-connection/CloudConnectionPanel.d.ts +1 -0
  36. package/dist/console/cloud-connection/CloudConnectionPanel.js +169 -0
  37. package/dist/console/home/AppCard.d.ts +1 -1
  38. package/dist/console/home/AppCard.js +6 -12
  39. package/dist/console/home/HomeAppsStrip.d.ts +8 -0
  40. package/dist/console/home/HomeAppsStrip.js +61 -0
  41. package/dist/console/home/HomeLayout.d.ts +1 -1
  42. package/dist/console/home/HomeLayout.js +3 -1
  43. package/dist/console/home/HomePage.d.ts +1 -2
  44. package/dist/console/home/HomePage.js +149 -21
  45. package/dist/console/home/HomeRail.d.ts +22 -0
  46. package/dist/console/home/HomeRail.js +62 -0
  47. package/dist/console/home/QuickActions.d.ts +1 -1
  48. package/dist/console/home/QuickActions.js +3 -11
  49. package/dist/console/home/RecentApps.d.ts +1 -1
  50. package/dist/console/home/RecentApps.js +2 -2
  51. package/dist/console/home/StarredApps.d.ts +1 -1
  52. package/dist/console/home/StarredApps.js +2 -2
  53. package/dist/console/marketplace/InstalledListWidget.d.ts +1 -0
  54. package/dist/console/marketplace/InstalledListWidget.js +93 -0
  55. package/dist/console/marketplace/MarkdownText.d.ts +1 -1
  56. package/dist/console/marketplace/MarketplaceAccessDenied.d.ts +1 -1
  57. package/dist/console/marketplace/MarketplaceInstalledPage.d.ts +8 -14
  58. package/dist/console/marketplace/MarketplaceInstalledPage.js +14 -66
  59. package/dist/console/marketplace/MarketplacePackagePage.d.ts +1 -1
  60. package/dist/console/marketplace/MarketplacePackagePage.js +249 -8
  61. package/dist/console/marketplace/MarketplacePage.d.ts +1 -1
  62. package/dist/console/marketplace/MarketplacePage.js +60 -3
  63. package/dist/console/marketplace/PackageIcon.d.ts +1 -1
  64. package/dist/console/marketplace/PluginDisclosure.d.ts +14 -0
  65. package/dist/console/marketplace/PluginDisclosure.js +38 -0
  66. package/dist/console/marketplace/marketplaceApi.d.ts +123 -0
  67. package/dist/console/marketplace/marketplaceApi.js +254 -1
  68. package/dist/console/organizations/CreateWorkspaceDialog.d.ts +1 -1
  69. package/dist/console/organizations/OrganizationsLayout.d.ts +1 -1
  70. package/dist/console/organizations/OrganizationsPage.d.ts +1 -1
  71. package/dist/console/organizations/manage/AcceptInvitationPage.d.ts +1 -1
  72. package/dist/console/organizations/manage/InvitationsPage.d.ts +1 -1
  73. package/dist/console/organizations/manage/InviteMemberDialog.d.ts +1 -1
  74. package/dist/console/organizations/manage/MembersPage.d.ts +1 -1
  75. package/dist/console/organizations/manage/OrganizationLayout.d.ts +1 -1
  76. package/dist/console/organizations/manage/SettingsPage.d.ts +1 -1
  77. package/dist/context/CommandPaletteProvider.d.ts +44 -0
  78. package/dist/context/CommandPaletteProvider.js +71 -0
  79. package/dist/context/FavoritesProvider.d.ts +1 -1
  80. package/dist/context/NavigationContext.d.ts +1 -1
  81. package/dist/context/RecentItemsProvider.d.ts +2 -2
  82. package/dist/context/UserStateAdapters.d.ts +1 -1
  83. package/dist/context/index.d.ts +2 -0
  84. package/dist/context/index.js +1 -0
  85. package/dist/hooks/index.d.ts +5 -2
  86. package/dist/hooks/index.js +4 -1
  87. package/dist/hooks/useActionModal.d.ts +53 -0
  88. package/dist/hooks/useActionModal.js +111 -0
  89. package/dist/hooks/useChatConversation.d.ts +137 -4
  90. package/dist/hooks/useChatConversation.js +316 -25
  91. package/dist/hooks/useConsoleActionRuntime.d.ts +70 -0
  92. package/dist/hooks/useConsoleActionRuntime.js +564 -0
  93. package/dist/hooks/useConversationList.js +61 -3
  94. package/dist/hooks/useHomeInbox.d.ts +13 -0
  95. package/dist/hooks/useHomeInbox.js +142 -0
  96. package/dist/hooks/useNavPins.js +17 -23
  97. package/dist/hooks/useNavigationSync.d.ts +33 -0
  98. package/dist/hooks/useNavigationSync.js +98 -12
  99. package/dist/hooks/useReconcileOnError.d.ts +40 -0
  100. package/dist/hooks/useReconcileOnError.js +37 -0
  101. package/dist/hooks/useRecordApprovals.d.ts +18 -19
  102. package/dist/hooks/useRecordApprovals.js +24 -40
  103. package/dist/hooks/useResponsiveSidebar.js +14 -5
  104. package/dist/hooks/useSettleSignal.d.ts +19 -0
  105. package/dist/hooks/useSettleSignal.js +20 -0
  106. package/dist/hooks/useTrackRouteAsRecent.js +35 -0
  107. package/dist/hooks/useUrlOverlay.d.ts +62 -0
  108. package/dist/hooks/useUrlOverlay.js +88 -0
  109. package/dist/index.d.ts +18 -8
  110. package/dist/index.js +17 -5
  111. package/dist/layout/ActivityFeed.d.ts +1 -1
  112. package/dist/layout/AppHeader.d.ts +3 -2
  113. package/dist/layout/AppHeader.js +237 -72
  114. package/dist/layout/AppSidebar.d.ts +2 -1
  115. package/dist/layout/AppSidebar.js +26 -46
  116. package/dist/layout/AppSwitcher.d.ts +2 -1
  117. package/dist/layout/AppSwitcher.js +9 -5
  118. package/dist/layout/AuthPageLayout.d.ts +1 -1
  119. package/dist/layout/ConnectionStatus.d.ts +1 -1
  120. package/dist/layout/ConnectionStatus.js +9 -6
  121. package/dist/layout/ConsoleChatbotFab.d.ts +19 -1
  122. package/dist/layout/ConsoleChatbotFab.js +16 -2
  123. package/dist/layout/ConsoleFloatingChatbot.d.ts +34 -2
  124. package/dist/layout/ConsoleFloatingChatbot.js +391 -41
  125. package/dist/layout/ConsoleLayout.d.ts +1 -1
  126. package/dist/layout/ConsoleLayout.js +27 -11
  127. package/dist/layout/ContextSelectors.d.ts +44 -0
  128. package/dist/layout/ContextSelectors.js +242 -0
  129. package/dist/layout/InboxPopover.d.ts +6 -1
  130. package/dist/layout/InboxPopover.js +25 -6
  131. package/dist/layout/LocaleSwitcher.d.ts +1 -1
  132. package/dist/layout/LocalizedSidebarTrigger.d.ts +2 -0
  133. package/dist/layout/LocalizedSidebarTrigger.js +15 -0
  134. package/dist/layout/MobileViewSwitcherContext.d.ts +1 -1
  135. package/dist/layout/ModeToggle.d.ts +1 -1
  136. package/dist/layout/PageHeader.d.ts +1 -1
  137. package/dist/layout/UnifiedSidebar.d.ts +2 -1
  138. package/dist/layout/UnifiedSidebar.js +116 -15
  139. package/dist/layout/agentPicker.d.ts +56 -0
  140. package/dist/layout/agentPicker.js +40 -0
  141. package/dist/observability/index.d.ts +1 -0
  142. package/dist/observability/index.js +1 -0
  143. package/dist/observability/settleSignal.d.ts +64 -0
  144. package/dist/observability/settleSignal.js +131 -0
  145. package/dist/preview/CommitTimeline.d.ts +15 -0
  146. package/dist/preview/CommitTimeline.js +82 -0
  147. package/dist/preview/DraftChangesPanel.d.ts +19 -0
  148. package/dist/preview/DraftChangesPanel.js +114 -0
  149. package/dist/preview/DraftPreviewBar.d.ts +8 -0
  150. package/dist/preview/DraftPreviewBar.js +86 -0
  151. package/dist/preview/PreviewDraftEmptyState.d.ts +16 -0
  152. package/dist/preview/PreviewDraftEmptyState.js +47 -0
  153. package/dist/preview/PreviewModeContext.d.ts +57 -0
  154. package/dist/preview/PreviewModeContext.js +99 -0
  155. package/dist/preview/UnpublishedAppBar.d.ts +8 -0
  156. package/dist/preview/UnpublishedAppBar.js +83 -0
  157. package/dist/preview/commitHistory.d.ts +28 -0
  158. package/dist/preview/commitHistory.js +48 -0
  159. package/dist/preview/draftStatus.d.ts +20 -0
  160. package/dist/preview/draftStatus.js +27 -0
  161. package/dist/preview/usePublishAllDrafts.d.ts +18 -0
  162. package/dist/preview/usePublishAllDrafts.js +106 -0
  163. package/dist/providers/AdapterProvider.d.ts +1 -1
  164. package/dist/providers/AdapterProvider.js +6 -1
  165. package/dist/providers/ExpressionProvider.d.ts +1 -1
  166. package/dist/providers/MetadataProvider.d.ts +17 -2
  167. package/dist/providers/MetadataProvider.js +192 -12
  168. package/dist/runtime-config.d.ts +46 -2
  169. package/dist/runtime-config.js +39 -2
  170. package/dist/services/builtinComponents.js +68 -59
  171. package/dist/skeletons/SkeletonDashboard.d.ts +1 -1
  172. package/dist/skeletons/SkeletonDetail.d.ts +1 -1
  173. package/dist/skeletons/SkeletonGrid.d.ts +1 -1
  174. package/dist/utils/appRoute.d.ts +21 -0
  175. package/dist/utils/appRoute.js +25 -0
  176. package/dist/utils/deriveRelatedLists.d.ts +54 -0
  177. package/dist/utils/deriveRelatedLists.js +91 -0
  178. package/dist/utils/index.d.ts +4 -0
  179. package/dist/utils/index.js +3 -0
  180. package/dist/utils/managedByEmptyState.d.ts +8 -1
  181. package/dist/utils/managedByEmptyState.js +13 -7
  182. package/dist/utils/preferLocal.d.ts +18 -0
  183. package/dist/utils/preferLocal.js +24 -0
  184. package/dist/views/ActionConfirmDialog.d.ts +1 -1
  185. package/dist/views/ActionConfirmDialog.js +3 -1
  186. package/dist/views/ActionParamDialog.d.ts +6 -1
  187. package/dist/views/ActionParamDialog.js +9 -3
  188. package/dist/views/ActionResultDialog.d.ts +13 -0
  189. package/dist/views/ActionResultDialog.js +134 -0
  190. package/dist/views/ComponentNavView.d.ts +14 -1
  191. package/dist/views/CreateViewDialog.d.ts +1 -1
  192. package/dist/views/DashboardConfigPanel.d.ts +28 -0
  193. package/dist/views/DashboardConfigPanel.js +81 -0
  194. package/dist/views/DashboardView.d.ts +4 -3
  195. package/dist/views/DashboardView.js +38 -239
  196. package/dist/views/FlowRunner.d.ts +31 -0
  197. package/dist/views/FlowRunner.js +121 -0
  198. package/dist/views/InterfaceListPage.d.ts +49 -0
  199. package/dist/views/InterfaceListPage.js +347 -0
  200. package/dist/views/MetadataInspector.d.ts +2 -2
  201. package/dist/views/ObjectView.d.ts +1 -1
  202. package/dist/views/ObjectView.js +209 -532
  203. package/dist/views/PageView.d.ts +8 -3
  204. package/dist/views/PageView.js +45 -32
  205. package/dist/views/RecordDetailView.d.ts +1 -1
  206. package/dist/views/RecordDetailView.js +363 -148
  207. package/dist/views/RecordFormPage.d.ts +1 -1
  208. package/dist/views/RecordFormPage.js +26 -1
  209. package/dist/views/ReportConfigPanel.d.ts +37 -0
  210. package/dist/views/ReportConfigPanel.js +85 -0
  211. package/dist/views/ReportView.d.ts +1 -1
  212. package/dist/views/ReportView.js +116 -7
  213. package/dist/views/RuntimeDraftBar.d.ts +30 -0
  214. package/dist/views/RuntimeDraftBar.js +112 -0
  215. package/dist/views/ScreenView.d.ts +70 -0
  216. package/dist/views/ScreenView.js +73 -0
  217. package/dist/views/SearchResultsPage.d.ts +1 -1
  218. package/dist/views/SearchResultsPage.js +8 -18
  219. package/dist/views/ViewConfigPanel.d.ts +24 -17
  220. package/dist/views/ViewConfigPanel.js +121 -77
  221. package/dist/views/index.d.ts +1 -1
  222. package/dist/views/index.js +1 -1
  223. package/dist/views/metadata-admin/AuditPanel.d.ts +28 -0
  224. package/dist/views/metadata-admin/AuditPanel.js +79 -0
  225. package/dist/views/metadata-admin/DiagnosticsPage.d.ts +20 -0
  226. package/dist/views/metadata-admin/DiagnosticsPage.js +69 -0
  227. package/dist/views/metadata-admin/DirectoryPage.d.ts +16 -1
  228. package/dist/views/metadata-admin/DirectoryPage.js +101 -24
  229. package/dist/views/metadata-admin/DraftReviewPanel.d.ts +33 -0
  230. package/dist/views/metadata-admin/DraftReviewPanel.js +77 -0
  231. package/dist/views/metadata-admin/EmbeddedItemEditor.d.ts +17 -1
  232. package/dist/views/metadata-admin/EmbeddedItemEditor.js +15 -8
  233. package/dist/views/metadata-admin/JsonSourceEditor.d.ts +39 -0
  234. package/dist/views/metadata-admin/JsonSourceEditor.js +196 -0
  235. package/dist/views/metadata-admin/LayeredDiff.d.ts +39 -1
  236. package/dist/views/metadata-admin/LayeredDiff.js +171 -5
  237. package/dist/views/metadata-admin/MetadataDetailDrawer.d.ts +15 -1
  238. package/dist/views/metadata-admin/MetadataTypeActions.d.ts +48 -0
  239. package/dist/views/metadata-admin/MetadataTypeActions.js +165 -0
  240. package/dist/views/metadata-admin/PackagesPage.d.ts +18 -0
  241. package/dist/views/metadata-admin/PackagesPage.js +403 -0
  242. package/dist/views/metadata-admin/PageShell.d.ts +1 -1
  243. package/dist/views/metadata-admin/PageShell.js +9 -4
  244. package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +35 -1
  245. package/dist/views/metadata-admin/QuickFind.d.ts +21 -1
  246. package/dist/views/metadata-admin/QuickFind.js +6 -3
  247. package/dist/views/metadata-admin/RelatedPanel.d.ts +24 -1
  248. package/dist/views/metadata-admin/RelatedPanel.js +20 -18
  249. package/dist/views/metadata-admin/ResourceEditPage.d.ts +40 -1
  250. package/dist/views/metadata-admin/ResourceEditPage.js +1250 -60
  251. package/dist/views/metadata-admin/ResourceHistoryPage.d.ts +39 -1
  252. package/dist/views/metadata-admin/ResourceHistoryPage.js +66 -16
  253. package/dist/views/metadata-admin/ResourceListPage.d.ts +13 -1
  254. package/dist/views/metadata-admin/ResourceListPage.js +258 -30
  255. package/dist/views/metadata-admin/ResourceRouter.d.ts +23 -1
  256. package/dist/views/metadata-admin/SchemaForm.d.ts +34 -1
  257. package/dist/views/metadata-admin/SchemaForm.js +559 -49
  258. package/dist/views/metadata-admin/StudioHomePage.d.ts +22 -0
  259. package/dist/views/metadata-admin/StudioHomePage.js +205 -0
  260. package/dist/views/metadata-admin/anchors.js +255 -24
  261. package/dist/views/metadata-admin/clientValidation.d.ts +50 -0
  262. package/dist/views/metadata-admin/clientValidation.js +169 -0
  263. package/dist/views/metadata-admin/color-variant-field.d.ts +30 -0
  264. package/dist/views/metadata-admin/color-variant-field.js +38 -0
  265. package/dist/views/metadata-admin/createDerive.d.ts +75 -0
  266. package/dist/views/metadata-admin/createDerive.js +179 -0
  267. package/dist/views/metadata-admin/dashboard-schema.d.ts +12 -0
  268. package/dist/views/metadata-admin/dashboard-schema.js +80 -0
  269. package/dist/views/metadata-admin/datasource/DatasourceResourcePage.d.ts +35 -0
  270. package/dist/views/metadata-admin/datasource/DatasourceResourcePage.js +327 -0
  271. package/dist/views/metadata-admin/datasource/register.d.ts +1 -0
  272. package/dist/views/metadata-admin/datasource/register.js +24 -0
  273. package/dist/views/metadata-admin/default-inspector-registry.d.ts +49 -0
  274. package/dist/views/metadata-admin/default-inspector-registry.js +8 -0
  275. package/dist/views/metadata-admin/default-schemas.js +115 -10
  276. package/dist/views/metadata-admin/external/ExternalDatasourcePanel.d.ts +27 -0
  277. package/dist/views/metadata-admin/external/ExternalDatasourcePanel.js +69 -0
  278. package/dist/views/metadata-admin/external/ImportObjectDialog.d.ts +27 -0
  279. package/dist/views/metadata-admin/external/ImportObjectDialog.js +77 -0
  280. package/dist/views/metadata-admin/external/SchemaBrowser.d.ts +16 -0
  281. package/dist/views/metadata-admin/external/SchemaBrowser.js +74 -0
  282. package/dist/views/metadata-admin/external/ValidationPanel.d.ts +16 -0
  283. package/dist/views/metadata-admin/external/ValidationPanel.js +68 -0
  284. package/dist/views/metadata-admin/external/api.d.ts +100 -0
  285. package/dist/views/metadata-admin/external/api.js +124 -0
  286. package/dist/views/metadata-admin/i18n.d.ts +1 -0
  287. package/dist/views/metadata-admin/i18n.js +1252 -2
  288. package/dist/views/metadata-admin/index.d.ts +8 -5
  289. package/dist/views/metadata-admin/index.js +12 -2
  290. package/dist/views/metadata-admin/inspector-registry.d.ts +51 -0
  291. package/dist/views/metadata-admin/inspector-registry.js +11 -0
  292. package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.d.ts +30 -0
  293. package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.js +180 -0
  294. package/dist/views/metadata-admin/inspectors/AppNavInspector.d.ts +16 -0
  295. package/dist/views/metadata-admin/inspectors/AppNavInspector.js +110 -0
  296. package/dist/views/metadata-admin/inspectors/ConditionBuilder.d.ts +29 -0
  297. package/dist/views/metadata-admin/inspectors/ConditionBuilder.js +154 -0
  298. package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.d.ts +28 -0
  299. package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.js +110 -0
  300. package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.d.ts +18 -0
  301. package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.js +139 -0
  302. package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.d.ts +21 -0
  303. package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.js +221 -0
  304. package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.d.ts +16 -0
  305. package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.js +126 -0
  306. package/dist/views/metadata-admin/inspectors/FlowInspector.d.ts +12 -0
  307. package/dist/views/metadata-admin/inspectors/FlowInspector.js +9 -0
  308. package/dist/views/metadata-admin/inspectors/FlowKeyValueField.d.ts +30 -0
  309. package/dist/views/metadata-admin/inspectors/FlowKeyValueField.js +125 -0
  310. package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.d.ts +18 -0
  311. package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.js +40 -0
  312. package/dist/views/metadata-admin/inspectors/FlowNodeInspector.d.ts +14 -0
  313. package/dist/views/metadata-admin/inspectors/FlowNodeInspector.js +205 -0
  314. package/dist/views/metadata-admin/inspectors/FlowObjectListField.d.ts +26 -0
  315. package/dist/views/metadata-admin/inspectors/FlowObjectListField.js +105 -0
  316. package/dist/views/metadata-admin/inspectors/FlowReferenceField.d.ts +83 -0
  317. package/dist/views/metadata-admin/inspectors/FlowReferenceField.js +181 -0
  318. package/dist/views/metadata-admin/inspectors/FlowStringListField.d.ts +21 -0
  319. package/dist/views/metadata-admin/inspectors/FlowStringListField.js +60 -0
  320. package/dist/views/metadata-admin/inspectors/InspectorComboField.d.ts +40 -0
  321. package/dist/views/metadata-admin/inspectors/InspectorComboField.js +61 -0
  322. package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.d.ts +21 -0
  323. package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.js +55 -0
  324. package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.d.ts +23 -0
  325. package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +365 -0
  326. package/dist/views/metadata-admin/inspectors/PageBlockInspector.d.ts +48 -0
  327. package/dist/views/metadata-admin/inspectors/PageBlockInspector.js +332 -0
  328. package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.d.ts +58 -0
  329. package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.js +218 -0
  330. package/dist/views/metadata-admin/inspectors/ViewColumnInspector.d.ts +19 -0
  331. package/dist/views/metadata-admin/inspectors/ViewColumnInspector.js +144 -0
  332. package/dist/views/metadata-admin/inspectors/ViewInspector.d.ts +19 -0
  333. package/dist/views/metadata-admin/inspectors/ViewInspector.js +21 -0
  334. package/dist/views/metadata-admin/inspectors/ViewVariantInspector.d.ts +54 -0
  335. package/dist/views/metadata-admin/inspectors/ViewVariantInspector.js +191 -0
  336. package/dist/views/metadata-admin/inspectors/_shared.d.ts +128 -0
  337. package/dist/views/metadata-admin/inspectors/_shared.js +113 -0
  338. package/dist/views/metadata-admin/inspectors/datasetFilterCondition.d.ts +24 -0
  339. package/dist/views/metadata-admin/inspectors/datasetFilterCondition.js +97 -0
  340. package/dist/views/metadata-admin/inspectors/expression-validate.d.ts +26 -0
  341. package/dist/views/metadata-admin/inspectors/expression-validate.js +66 -0
  342. package/dist/views/metadata-admin/inspectors/flow-node-config.d.ts +143 -0
  343. package/dist/views/metadata-admin/inspectors/flow-node-config.js +506 -0
  344. package/dist/views/metadata-admin/inspectors/index.d.ts +1 -0
  345. package/dist/views/metadata-admin/inspectors/index.js +45 -0
  346. package/dist/views/metadata-admin/inspectors/json-schema-to-fields.d.ts +40 -0
  347. package/dist/views/metadata-admin/inspectors/json-schema-to-fields.js +227 -0
  348. package/dist/views/metadata-admin/inspectors/useDatasetFields.d.ts +72 -0
  349. package/dist/views/metadata-admin/inspectors/useDatasetFields.js +0 -0
  350. package/dist/views/metadata-admin/issuePath.d.ts +22 -0
  351. package/dist/views/metadata-admin/issuePath.js +65 -0
  352. package/dist/views/metadata-admin/mergeServerFields.d.ts +65 -0
  353. package/dist/views/metadata-admin/mergeServerFields.js +56 -0
  354. package/dist/views/metadata-admin/package-scope.d.ts +26 -0
  355. package/dist/views/metadata-admin/package-scope.js +43 -0
  356. package/dist/views/metadata-admin/preview-registry.d.ts +55 -0
  357. package/dist/views/metadata-admin/previews/ActionPreview.d.ts +25 -0
  358. package/dist/views/metadata-admin/previews/ActionPreview.js +238 -0
  359. package/dist/views/metadata-admin/previews/AddWidgetPicker.d.ts +12 -0
  360. package/dist/views/metadata-admin/previews/AddWidgetPicker.js +56 -0
  361. package/dist/views/metadata-admin/previews/AgentPreview.d.ts +24 -0
  362. package/dist/views/metadata-admin/previews/AgentPreview.js +100 -0
  363. package/dist/views/metadata-admin/previews/AppNavCanvas.d.ts +31 -0
  364. package/dist/views/metadata-admin/previews/AppNavCanvas.js +260 -0
  365. package/dist/views/metadata-admin/previews/AppPreview.d.ts +16 -1
  366. package/dist/views/metadata-admin/previews/AppPreview.js +23 -14
  367. package/dist/views/metadata-admin/previews/BookPreview.d.ts +20 -0
  368. package/dist/views/metadata-admin/previews/BookPreview.js +132 -0
  369. package/dist/views/metadata-admin/previews/DashboardPreview.d.ts +16 -1
  370. package/dist/views/metadata-admin/previews/DashboardPreview.js +110 -8
  371. package/dist/views/metadata-admin/previews/DatasetPreview.d.ts +18 -0
  372. package/dist/views/metadata-admin/previews/DatasetPreview.js +105 -0
  373. package/dist/views/metadata-admin/previews/DatasourcePreview.d.ts +23 -0
  374. package/dist/views/metadata-admin/previews/DatasourcePreview.js +68 -0
  375. package/dist/views/metadata-admin/previews/EmailTemplatePreview.d.ts +14 -1
  376. package/dist/views/metadata-admin/previews/FieldStub.d.ts +30 -0
  377. package/dist/views/metadata-admin/previews/FieldStub.js +104 -0
  378. package/dist/views/metadata-admin/previews/FieldsListEditor.d.ts +50 -0
  379. package/dist/views/metadata-admin/previews/FieldsListEditor.js +97 -0
  380. package/dist/views/metadata-admin/previews/FlowCanvas.d.ts +49 -0
  381. package/dist/views/metadata-admin/previews/FlowCanvas.js +416 -0
  382. package/dist/views/metadata-admin/previews/FlowPreview.d.ts +20 -0
  383. package/dist/views/metadata-admin/previews/FlowPreview.js +120 -0
  384. package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +46 -0
  385. package/dist/views/metadata-admin/previews/FlowRunsPanel.js +97 -0
  386. package/dist/views/metadata-admin/previews/FlowSimulatorPanel.d.ts +25 -0
  387. package/dist/views/metadata-admin/previews/FlowSimulatorPanel.js +204 -0
  388. package/dist/views/metadata-admin/previews/JobPreview.d.ts +28 -0
  389. package/dist/views/metadata-admin/previews/JobPreview.js +290 -0
  390. package/dist/views/metadata-admin/previews/ObjectFormCanvas.d.ts +30 -0
  391. package/dist/views/metadata-admin/previews/ObjectFormCanvas.js +547 -0
  392. package/dist/views/metadata-admin/previews/ObjectPreview.d.ts +14 -1
  393. package/dist/views/metadata-admin/previews/ObjectPreview.js +5 -30
  394. package/dist/views/metadata-admin/previews/OutlineStrip.d.ts +32 -0
  395. package/dist/views/metadata-admin/previews/OutlineStrip.js +8 -0
  396. package/dist/views/metadata-admin/previews/PageBlockCanvas.d.ts +49 -0
  397. package/dist/views/metadata-admin/previews/PageBlockCanvas.js +510 -0
  398. package/dist/views/metadata-admin/previews/PagePreview.d.ts +10 -1
  399. package/dist/views/metadata-admin/previews/PagePreview.js +200 -5
  400. package/dist/views/metadata-admin/previews/PermissionPreview.d.ts +27 -0
  401. package/dist/views/metadata-admin/previews/PermissionPreview.js +115 -0
  402. package/dist/views/metadata-admin/previews/PreviewShell.d.ts +29 -6
  403. package/dist/views/metadata-admin/previews/PreviewShell.js +16 -3
  404. package/dist/views/metadata-admin/previews/ReportPreview.d.ts +18 -1
  405. package/dist/views/metadata-admin/previews/ReportPreview.js +23 -15
  406. package/dist/views/metadata-admin/previews/RolePreview.d.ts +19 -0
  407. package/dist/views/metadata-admin/previews/RolePreview.js +14 -0
  408. package/dist/views/metadata-admin/previews/ScreenPreview.d.ts +38 -0
  409. package/dist/views/metadata-admin/previews/ScreenPreview.js +61 -0
  410. package/dist/views/metadata-admin/previews/SkillPreview.d.ts +22 -0
  411. package/dist/views/metadata-admin/previews/SkillPreview.js +34 -0
  412. package/dist/views/metadata-admin/previews/ToolPreview.d.ts +25 -0
  413. package/dist/views/metadata-admin/previews/ToolPreview.js +122 -0
  414. package/dist/views/metadata-admin/previews/TranslationPreview.d.ts +25 -0
  415. package/dist/views/metadata-admin/previews/TranslationPreview.js +52 -0
  416. package/dist/views/metadata-admin/previews/ValidationPreview.d.ts +27 -0
  417. package/dist/views/metadata-admin/previews/ValidationPreview.js +110 -0
  418. package/dist/views/metadata-admin/previews/ViewColumnPanes.d.ts +62 -0
  419. package/dist/views/metadata-admin/previews/ViewColumnPanes.js +140 -0
  420. package/dist/views/metadata-admin/previews/ViewPreview.d.ts +23 -1
  421. package/dist/views/metadata-admin/previews/ViewPreview.js +101 -73
  422. package/dist/views/metadata-admin/previews/block-config.d.ts +82 -0
  423. package/dist/views/metadata-admin/previews/block-config.js +324 -0
  424. package/dist/views/metadata-admin/previews/block-types.d.ts +40 -0
  425. package/dist/views/metadata-admin/previews/block-types.js +110 -0
  426. package/dist/views/metadata-admin/previews/field-types.d.ts +53 -0
  427. package/dist/views/metadata-admin/previews/field-types.js +97 -0
  428. package/dist/views/metadata-admin/previews/flow-canvas-layout.d.ts +102 -0
  429. package/dist/views/metadata-admin/previews/flow-canvas-layout.js +227 -0
  430. package/dist/views/metadata-admin/previews/flow-canvas-parts.d.ts +96 -0
  431. package/dist/views/metadata-admin/previews/flow-canvas-parts.js +373 -0
  432. package/dist/views/metadata-admin/previews/form-preview.d.ts +24 -0
  433. package/dist/views/metadata-admin/previews/form-preview.js +29 -0
  434. package/dist/views/metadata-admin/previews/index.js +43 -0
  435. package/dist/views/metadata-admin/previews/object-fields-bridge.d.ts +66 -0
  436. package/dist/views/metadata-admin/previews/object-fields-bridge.js +171 -0
  437. package/dist/views/metadata-admin/previews/object-fields-io.d.ts +130 -0
  438. package/dist/views/metadata-admin/previews/object-fields-io.js +243 -0
  439. package/dist/views/metadata-admin/previews/screen-spec.d.ts +43 -0
  440. package/dist/views/metadata-admin/previews/screen-spec.js +108 -0
  441. package/dist/views/metadata-admin/previews/simulator/flow-sim-types.d.ts +102 -0
  442. package/dist/views/metadata-admin/previews/simulator/flow-sim-types.js +2 -0
  443. package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.d.ts +15 -0
  444. package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.js +185 -0
  445. package/dist/views/metadata-admin/previews/simulator/flow-simulator.d.ts +73 -0
  446. package/dist/views/metadata-admin/previews/simulator/flow-simulator.js +426 -0
  447. package/dist/views/metadata-admin/previews/useDatasetCatalog.d.ts +47 -0
  448. package/dist/views/metadata-admin/previews/useDatasetCatalog.js +133 -0
  449. package/dist/views/metadata-admin/previews/useFlowNodePalette.d.ts +44 -0
  450. package/dist/views/metadata-admin/previews/useFlowNodePalette.js +124 -0
  451. package/dist/views/metadata-admin/previews/useMetaOptions.d.ts +8 -0
  452. package/dist/views/metadata-admin/previews/useMetaOptions.js +50 -0
  453. package/dist/views/metadata-admin/previews/useObjectFields.d.ts +23 -0
  454. package/dist/views/metadata-admin/previews/useObjectFields.js +79 -0
  455. package/dist/views/metadata-admin/previews/useObjectOptions.d.ts +8 -0
  456. package/dist/views/metadata-admin/previews/useObjectOptions.js +43 -0
  457. package/dist/views/metadata-admin/previews/view-column-io.d.ts +42 -0
  458. package/dist/views/metadata-admin/previews/view-column-io.js +73 -0
  459. package/dist/views/metadata-admin/previews/widget-types.d.ts +24 -0
  460. package/dist/views/metadata-admin/previews/widget-types.js +40 -0
  461. package/dist/views/metadata-admin/registry.d.ts +140 -19
  462. package/dist/views/metadata-admin/report-schema.d.ts +26 -0
  463. package/dist/views/metadata-admin/report-schema.js +121 -0
  464. package/dist/views/metadata-admin/useMetadata.d.ts +100 -2
  465. package/dist/views/metadata-admin/useMetadata.js +155 -4
  466. package/dist/views/metadata-admin/view-item-normalize.d.ts +20 -0
  467. package/dist/views/metadata-admin/view-item-normalize.js +68 -0
  468. package/dist/views/metadata-admin/view-schema.d.ts +16 -0
  469. package/dist/views/metadata-admin/view-schema.js +107 -0
  470. package/dist/views/metadata-admin/view-variant-model.d.ts +23 -0
  471. package/dist/views/metadata-admin/view-variant-model.js +64 -0
  472. package/dist/views/metadata-admin/widgets.d.ts +89 -1
  473. package/dist/views/metadata-admin/widgets.js +491 -17
  474. package/dist/views/runtime-metadata-persistence.d.ts +78 -0
  475. package/dist/views/runtime-metadata-persistence.js +89 -0
  476. package/dist/views/useOpenRecordList.d.ts +18 -0
  477. package/dist/views/useOpenRecordList.js +36 -0
  478. package/dist/views/userFilterUrlState.d.ts +15 -0
  479. package/dist/views/userFilterUrlState.js +53 -0
  480. package/dist/views/view-config-adapter.d.ts +38 -0
  481. package/dist/views/view-config-adapter.js +80 -0
  482. package/package.json +52 -34
  483. package/dist/views/DesignDrawer.d.ts +0 -28
  484. package/dist/views/DesignDrawer.js +0 -51
  485. package/dist/views/metadata-admin/DesignerEditorWrapper.d.ts +0 -68
  486. package/dist/views/metadata-admin/DesignerEditorWrapper.js +0 -158
@@ -0,0 +1,169 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
3
+ /**
4
+ * CloudConnectionPanel — the RFC 8628 device-code binding state machine,
5
+ * registered as the SDUI widget `cloud-connection:panel`.
6
+ *
7
+ * This is deliberately the ONLY React in the Cloud Connection surface:
8
+ * the page shell, nav placement and labels ship as metadata WITH the
9
+ * `@objectstack/cloud-connection` plugin (cloud ADR-0008 / console
10
+ * SDUI-first direction). The widget talks to the runtime's same-origin
11
+ * `/api/v1/cloud-connection/*` routes.
12
+ *
13
+ * Zero-input flow (ADR runtime-identity-binding §2.3): [Connect] →
14
+ * bind/start (no environment id — the registration is created cloud-side
15
+ * at approval) → the approval page auto-opens in a popup with the code
16
+ * pre-filled and the device named → bind/poll … → bound. The visible
17
+ * user code is the popup-blocked fallback, not the primary path.
18
+ *
19
+ * The runtime credential never reaches the browser — bind/poll persists
20
+ * it server-side and strips it from the response.
21
+ */
22
+ import { useCallback, useEffect, useRef, useState } from 'react';
23
+ import { Cloud, CloudOff, Copy, ExternalLink, Loader2, AlertCircle, CheckCircle2, Unplug, } from 'lucide-react';
24
+ import { ComponentRegistry } from '@object-ui/core';
25
+ const BASE = '/api/v1/cloud-connection';
26
+ async function getJson(url, init) {
27
+ const resp = await fetch(url, {
28
+ credentials: 'same-origin',
29
+ headers: { 'Content-Type': 'application/json' },
30
+ ...init,
31
+ });
32
+ const body = await resp.json().catch(() => ({}));
33
+ if (!resp.ok && body?.success !== true) {
34
+ const msg = body?.error?.message ?? body?.error?.code ?? body?.error ?? `HTTP ${resp.status}`;
35
+ throw new Error(typeof msg === 'string' ? msg : JSON.stringify(msg));
36
+ }
37
+ return body;
38
+ }
39
+ export function CloudConnectionPanel() {
40
+ const [phase, setPhase] = useState({ kind: 'loading' });
41
+ const [busy, setBusy] = useState(false);
42
+ const [copied, setCopied] = useState(false);
43
+ const pollTimer = useRef(null);
44
+ const stopPolling = useCallback(() => {
45
+ if (pollTimer.current) {
46
+ clearTimeout(pollTimer.current);
47
+ pollTimer.current = null;
48
+ }
49
+ }, []);
50
+ const refreshStatus = useCallback(async () => {
51
+ try {
52
+ const body = await getJson(`${BASE}/status`);
53
+ const data = body?.data ?? { environmentId: null, bound: false, connection: null };
54
+ setPhase(data.bound ? { kind: 'bound', status: data } : { kind: 'unbound' });
55
+ }
56
+ catch (err) {
57
+ setPhase({ kind: 'error', message: err?.message ?? String(err) });
58
+ }
59
+ }, []);
60
+ useEffect(() => {
61
+ void refreshStatus();
62
+ return stopPolling;
63
+ }, [refreshStatus, stopPolling]);
64
+ const poll = useCallback((code, startedAt) => {
65
+ const intervalMs = Math.max(code.interval, 2) * 1000;
66
+ const tick = async () => {
67
+ if (Date.now() - startedAt > code.expires_in * 1000) {
68
+ setPhase({ kind: 'error', message: 'The request expired before it was approved. Start again.' });
69
+ return;
70
+ }
71
+ try {
72
+ const body = await getJson(`${BASE}/bind/poll`, {
73
+ method: 'POST',
74
+ body: JSON.stringify({ device_code: code.device_code }),
75
+ });
76
+ if (body?.data?.pending) {
77
+ pollTimer.current = setTimeout(tick, intervalMs);
78
+ return;
79
+ }
80
+ if (body?.data?.bound || body?.success) {
81
+ await refreshStatus();
82
+ return;
83
+ }
84
+ setPhase({ kind: 'error', message: body?.error?.code ?? 'Binding failed.' });
85
+ }
86
+ catch (err) {
87
+ setPhase({ kind: 'error', message: err?.message ?? String(err) });
88
+ }
89
+ };
90
+ pollTimer.current = setTimeout(tick, intervalMs);
91
+ }, [refreshStatus]);
92
+ const connect = useCallback(async () => {
93
+ setBusy(true);
94
+ try {
95
+ const body = await getJson(`${BASE}/bind/start`, { method: 'POST', body: '{}' });
96
+ const code = body?.data;
97
+ if (!code?.device_code || !code?.user_code)
98
+ throw new Error('Device code request failed.');
99
+ // Auto-open the approval page — the GitHub-login moment. Still within
100
+ // the click's transient activation, so popup blockers generally allow
101
+ // it; the code display below is the blocked-popup fallback.
102
+ const link = code.verification_uri_complete ?? code.verification_uri;
103
+ let popupOpened = false;
104
+ if (link) {
105
+ try {
106
+ popupOpened = Boolean(window.open(link, '_blank', 'noopener,width=520,height=720'));
107
+ }
108
+ catch { /* blocked — fallback UI below */ }
109
+ }
110
+ setPhase({ kind: 'waiting', code, popupOpened });
111
+ poll(code, Date.now());
112
+ }
113
+ catch (err) {
114
+ setPhase({ kind: 'error', message: err?.message ?? String(err) });
115
+ }
116
+ finally {
117
+ setBusy(false);
118
+ }
119
+ }, [poll]);
120
+ const disconnect = useCallback(async () => {
121
+ setBusy(true);
122
+ try {
123
+ await getJson(`${BASE}/unbind`, { method: 'POST', body: '{}' });
124
+ await refreshStatus();
125
+ }
126
+ catch (err) {
127
+ setPhase({ kind: 'error', message: err?.message ?? String(err) });
128
+ }
129
+ finally {
130
+ setBusy(false);
131
+ }
132
+ }, [refreshStatus]);
133
+ const copyCode = useCallback(async (code) => {
134
+ try {
135
+ await navigator.clipboard.writeText(code);
136
+ setCopied(true);
137
+ setTimeout(() => setCopied(false), 1500);
138
+ }
139
+ catch { /* clipboard unavailable — user can select the text */ }
140
+ }, []);
141
+ if (phase.kind === 'loading') {
142
+ return (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border p-6 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" }), " Checking connection\u2026"] }));
143
+ }
144
+ if (phase.kind === 'error') {
145
+ return (_jsxs("div", { className: "flex flex-col gap-3 rounded-lg border border-destructive/40 bg-destructive/5 p-6", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm text-destructive", children: [_jsx(AlertCircle, { className: "h-4 w-4", "aria-hidden": "true" }), " ", phase.message] }), _jsx("button", { type: "button", className: "self-start rounded-md border px-3 py-1.5 text-sm hover:bg-accent", onClick: () => { stopPolling(); void refreshStatus(); }, children: "Try again" })] }));
146
+ }
147
+ if (phase.kind === 'waiting') {
148
+ const link = phase.code.verification_uri_complete ?? phase.code.verification_uri;
149
+ return (_jsxs("div", { className: "flex flex-col gap-4 rounded-lg border p-6", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" }), phase.popupOpened
150
+ ? 'Approve the connection in the window that just opened — this page updates by itself.'
151
+ : 'Waiting for approval in the cloud console…'] }), !phase.popupOpened && link ? (_jsxs("a", { className: "inline-flex items-center gap-1.5 self-start rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90", href: link, target: "_blank", rel: "noreferrer", children: ["Open the approval page ", _jsx(ExternalLink, { className: "h-3.5 w-3.5", "aria-hidden": "true" })] })) : null, _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("code", { className: "rounded-md bg-muted px-4 py-2 text-2xl font-semibold tracking-[0.25em]", children: phase.code.user_code }), _jsxs("button", { type: "button", className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-accent", onClick: () => void copyCode(phase.code.user_code), children: [_jsx(Copy, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), " ", copied ? 'Copied' : 'Copy'] })] }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["The code is pre-filled on the approval page", phase.popupOpened && link ? (_jsxs(_Fragment, { children: [' ', "\u2014 if the window did not appear,", ' ', _jsxs("a", { className: "inline-flex items-center gap-1 text-primary underline-offset-2 hover:underline", href: link, target: "_blank", rel: "noreferrer", children: ["open it here ", _jsx(ExternalLink, { className: "h-3 w-3", "aria-hidden": "true" })] }), "."] })) : '.'] }), _jsx("button", { type: "button", className: "self-start rounded-md border px-3 py-1.5 text-sm hover:bg-accent", onClick: () => { stopPolling(); void refreshStatus(); }, children: "Cancel" })] }));
152
+ }
153
+ if (phase.kind === 'bound') {
154
+ const conn = phase.status.connection ?? {};
155
+ const runtimeId = conn.runtime_id ?? phase.status.runtimeId;
156
+ return (_jsxs("div", { className: "flex flex-col gap-4 rounded-lg border p-6", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-5 w-5 text-emerald-600", "aria-hidden": "true" }), _jsx("span", { className: "font-medium", children: "Connected to ObjectStack Cloud" })] }), _jsxs("dl", { className: "grid grid-cols-[auto_1fr] gap-x-6 gap-y-1.5 text-sm", children: [conn.name ? (_jsxs(_Fragment, { children: [_jsx("dt", { className: "text-muted-foreground", children: "Runtime" }), _jsx("dd", { children: conn.name })] })) : null, conn.organization_id ? (_jsxs(_Fragment, { children: [_jsx("dt", { className: "text-muted-foreground", children: "Organization" }), _jsx("dd", { className: "font-mono", children: conn.organization_id })] })) : null, conn.account_email ? (_jsxs(_Fragment, { children: [_jsx("dt", { className: "text-muted-foreground", children: "Approved by" }), _jsx("dd", { children: conn.account_email })] })) : null, runtimeId ? (_jsxs(_Fragment, { children: [_jsx("dt", { className: "text-muted-foreground", children: "Runtime ID" }), _jsx("dd", { className: "font-mono text-xs", children: runtimeId })] })) : null, phase.status.environmentId ? (_jsxs(_Fragment, { children: [_jsx("dt", { className: "text-muted-foreground", children: "Environment" }), _jsx("dd", { className: "font-mono", children: phase.status.environmentId })] })) : null, conn.bound_at ? (_jsxs(_Fragment, { children: [_jsx("dt", { className: "text-muted-foreground", children: "Since" }), _jsx("dd", { children: new Date(conn.bound_at).toLocaleString() })] })) : null] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Your organization's private packages now appear in the Marketplace under \u201CYour organization\u201D." }), _jsxs("button", { type: "button", disabled: busy, className: "inline-flex items-center gap-1.5 self-start rounded-md border border-destructive/40 px-3 py-1.5 text-sm text-destructive hover:bg-destructive/5 disabled:opacity-50", onClick: () => void disconnect(), children: [_jsx(Unplug, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), " Disconnect"] })] }));
157
+ }
158
+ // unbound — zero input: no environment id, nothing to paste anywhere.
159
+ return (_jsxs("div", { className: "flex flex-col gap-4 rounded-lg border p-6", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CloudOff, { className: "h-5 w-5 text-muted-foreground", "aria-hidden": "true" }), _jsx("span", { className: "font-medium", children: "Not connected" })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Connect this runtime to an ObjectStack control plane to browse your organization's private packages and install them here. Approval is a single click in your cloud account \u2014 no ids or credentials are typed into this page." }), _jsxs("button", { type: "button", disabled: busy, className: "inline-flex items-center gap-1.5 self-start rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50", onClick: () => void connect(), children: [busy ? _jsx(Loader2, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" }) : _jsx(Cloud, { className: "h-4 w-4", "aria-hidden": "true" }), "Connect"] })] }));
160
+ }
161
+ // SDUI registration: page metadata (shipped by @objectstack/cloud-connection)
162
+ // references this widget by type. The renderer passes the component node as
163
+ // `schema`; the panel needs no properties today.
164
+ ComponentRegistry.register('cloud-connection:panel', () => _jsx(CloudConnectionPanel, {}), {
165
+ namespace: 'app-shell',
166
+ label: 'Cloud Connection Panel',
167
+ category: 'plugin',
168
+ inputs: [],
169
+ });
@@ -11,5 +11,5 @@ interface AppCardProps {
11
11
  isFavorite: boolean;
12
12
  index?: number;
13
13
  }
14
- export declare function AppCard({ app, onClick, isFavorite, index }: AppCardProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function AppCard({ app, onClick, isFavorite, index }: AppCardProps): import("react").JSX.Element;
15
15
  export {};
@@ -9,7 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  import { Star, StarOff, ArrowUpRight } from 'lucide-react';
10
10
  import { Card, CardContent, Button, Badge } from '@object-ui/components';
11
11
  import { useObjectTranslation, useObjectLabel } from '@object-ui/i18n';
12
- import { resolveI18nLabel } from '../../utils';
12
+ import { resolveI18nLabel, appRouteSegment } from '../../utils';
13
13
  import { useFavorites } from '../../hooks/useFavorites';
14
14
  import { getIcon } from '../../utils/getIcon';
15
15
  import { cn } from '@object-ui/components';
@@ -36,25 +36,19 @@ export function AppCard({ app, onClick, isFavorite, index = 0 }) {
36
36
  const Icon = getIcon(app.icon);
37
37
  const label = appLabel({ name: app.name, label: resolveI18nLabel(app.label, t) });
38
38
  const description = appDescription({ name: app.name, description: resolveI18nLabel(app.description, t) });
39
- const primaryColor = app.branding?.primaryColor;
40
39
  const accent = ACCENTS[(hashStr(app.name) + index) % ACCENTS.length];
41
40
  const handleToggleFavorite = (e) => {
42
41
  e.stopPropagation();
43
42
  toggleFavorite({
44
43
  id: `app:${app.name}`,
45
44
  label,
46
- href: `/apps/${app.name}`,
45
+ // ADR-0048 — link to the canonical package-id route segment, not the
46
+ // app name, so the favorite opens `/apps/<packageId>` like the nav does.
47
+ href: `/apps/${appRouteSegment(app) ?? app.name}`,
47
48
  type: 'object',
48
49
  });
49
50
  };
50
- return (_jsxs(Card, { role: "button", tabIndex: 0, "aria-label": label, className: cn('group relative cursor-pointer overflow-hidden border border-border/70 bg-card/80 backdrop-blur-sm', 'transition-[transform,box-shadow,border-color] duration-200 hover:-translate-y-0.5 hover:shadow-lg', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', 'motion-reduce:transition-none motion-reduce:hover:transform-none', !primaryColor && accent.ring), onClick: onClick, onKeyDown: (e) => {
51
- if (e.key === 'Enter' || e.key === ' ') {
52
- e.preventDefault();
53
- onClick();
54
- }
55
- }, "data-testid": `app-card-${app.name}`, style: primaryColor ? { borderColor: undefined } : undefined, children: [_jsx("div", { "aria-hidden": true, className: cn('absolute inset-x-0 top-0 h-1', primaryColor ? '' : accent.solid), style: primaryColor ? { backgroundColor: primaryColor } : undefined }), !primaryColor && (_jsx("div", { "aria-hidden": true, className: cn('absolute inset-0 bg-gradient-to-br opacity-0 transition-opacity duration-300 group-hover:opacity-100', accent.from, accent.to) })), _jsxs(CardContent, { className: "relative p-5", children: [_jsx(Button, { variant: "ghost", size: "sm", className: "absolute top-2 right-2 h-8 w-8 p-0 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 transition-opacity", onClick: handleToggleFavorite, "aria-label": isFavorite
51
+ return (_jsxs(Card, { className: cn('group relative overflow-hidden border border-border/70 bg-card/80 backdrop-blur-sm', 'transition-[transform,box-shadow,border-color] duration-200 hover:-translate-y-0.5 hover:shadow-lg active:scale-[0.985] active:-translate-y-0', 'motion-reduce:transition-none motion-reduce:hover:transform-none', accent.ring), "data-testid": `app-card-${app.name}`, children: [_jsx("button", { type: "button", "aria-label": label, className: "absolute inset-0 z-10 rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", onClick: onClick, "data-testid": `app-card-open-${app.name}` }), _jsx("div", { "aria-hidden": true, className: cn('absolute inset-0 bg-gradient-to-br opacity-0 transition-opacity duration-300 group-hover:opacity-100', accent.from, accent.to) }), _jsxs(CardContent, { className: "relative flex h-full flex-col p-5", children: [_jsx(Button, { variant: "ghost", size: "sm", className: "absolute top-2 right-2 z-20 h-8 w-8 p-0 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100", onClick: handleToggleFavorite, "aria-label": isFavorite
56
52
  ? t('common.removeFromFavorites', { defaultValue: 'Remove from favorites' }) + ` — ${label}`
57
- : t('common.addToFavorites', { defaultValue: 'Add to favorites' }) + ` — ${label}`, "aria-pressed": isFavorite, "data-testid": `favorite-btn-${app.name}`, children: isFavorite ? (_jsx(Star, { className: "h-4 w-4 fill-amber-400 text-amber-400" })) : (_jsx(StarOff, { className: "h-4 w-4" })) }), _jsx("div", { className: cn('inline-flex h-14 w-14 items-center justify-center rounded-xl mb-4 ring-1 ring-inset', primaryColor ? '' : cn('bg-gradient-to-br', accent.from, accent.to, 'ring-border/40')), style: primaryColor
58
- ? { backgroundColor: `${primaryColor}1f`, boxShadow: `inset 0 0 0 1px ${primaryColor}33` }
59
- : undefined, children: _jsx(Icon, { className: cn('h-7 w-7', primaryColor ? '' : accent.text), style: primaryColor ? { color: primaryColor } : undefined }) }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h3", { className: "font-semibold text-base sm:text-lg leading-tight truncate", children: label }), app.isDefault && (_jsx(Badge, { variant: "secondary", className: "shrink-0 text-[10px] px-1.5 py-0", children: t('home.appCard.default', { defaultValue: 'Default' }) }))] }), _jsx("p", { className: cn('text-sm text-muted-foreground mt-1.5 line-clamp-2 min-h-[2.5rem]', !description && 'italic'), children: description || t('home.appCard.noDescription', { defaultValue: 'No description' }) })] }), _jsx("div", { className: "mt-4 flex items-center justify-between text-xs font-medium", children: _jsxs("span", { className: "inline-flex items-center gap-1 text-muted-foreground transition-colors group-hover:text-foreground", children: [t('home.open', { defaultValue: 'Open' }), _jsx(ArrowUpRight, { className: "h-3.5 w-3.5 transition-transform duration-200 group-hover:translate-x-0.5 group-hover:-translate-y-0.5" })] }) })] })] }));
53
+ : t('common.addToFavorites', { defaultValue: 'Add to favorites' }) + ` — ${label}`, "aria-pressed": isFavorite, "data-testid": `favorite-btn-${app.name}`, children: isFavorite ? (_jsx(Star, { className: "h-4 w-4 fill-amber-400 text-amber-400" })) : (_jsx(StarOff, { className: "h-4 w-4" })) }), _jsx("div", { className: cn('inline-flex h-14 w-14 items-center justify-center rounded-2xl mb-4 ring-1 ring-inset', 'bg-gradient-to-br ring-border/40', accent.from, accent.to), children: _jsx(Icon, { className: cn('h-7 w-7', accent.text) }) }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h3", { className: "font-semibold text-base sm:text-lg leading-tight truncate", children: label }), app.isDefault && (_jsx(Badge, { variant: "secondary", className: "shrink-0 text-[10px] px-1.5 py-0", children: t('home.appCard.default', { defaultValue: 'Default' }) }))] }), _jsx("p", { className: "text-sm text-muted-foreground mt-1.5 line-clamp-2 min-h-[2.5rem]", children: description || t('home.appCard.noDescription', { defaultValue: 'No description' }) })] }), _jsx("div", { className: "mt-auto pt-4 flex items-center justify-between text-xs font-medium", children: _jsxs("span", { className: "inline-flex items-center gap-1 text-muted-foreground transition-colors group-hover:text-foreground", children: [t('home.open', { defaultValue: 'Open' }), _jsx(ArrowUpRight, { className: "h-3.5 w-3.5 transition-transform duration-200 group-hover:translate-x-0.5 group-hover:-translate-y-0.5" })] }) })] })] }));
60
54
  }
@@ -0,0 +1,8 @@
1
+ import type { FavoriteItem } from '../../hooks/useFavorites';
2
+ export declare function HomeAppsStrip({ apps, favorites, onOpen, onBrowseMarketplace, isAdmin, }: {
3
+ apps: any[];
4
+ favorites: FavoriteItem[];
5
+ onOpen: (app: any) => void;
6
+ onBrowseMarketplace: () => void;
7
+ isAdmin: boolean;
8
+ }): import("react").JSX.Element;
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * HomeAppsStrip
4
+ *
5
+ * iOS-springboard-style app launcher for Home: vibrant gradient squircle
6
+ * icons with the name beneath. Business users live in a handful of apps and
7
+ * switch via the top-bar AppSwitcher / ⌘K — so Home shows apps as recognizable
8
+ * icons, not a wall of marketing cards.
9
+ *
10
+ * Scales from a few apps to hundreds: a capped grid with a "+N more / Show all"
11
+ * toggle keeps the fold stable no matter how many apps exist. Favorites sort
12
+ * first.
13
+ *
14
+ * @module
15
+ */
16
+ import { useMemo, useState } from 'react';
17
+ import { LayoutGrid, Store, Star } from 'lucide-react';
18
+ import { Button, cn } from '@object-ui/components';
19
+ import { useObjectTranslation, useObjectLabel } from '@object-ui/i18n';
20
+ import { resolveI18nLabel } from '../../utils';
21
+ import { getIcon } from '../../utils/getIcon';
22
+ const COMPACT_LIMIT = 19;
23
+ // iOS-springboard icon tints: a vibrant gradient per app, assigned
24
+ // deterministically by name so an app keeps its colour across sessions.
25
+ // (Literal class strings so Tailwind's source scan emits them.)
26
+ const ICON_GRADIENTS = [
27
+ 'from-blue-500 to-indigo-600',
28
+ 'from-violet-500 to-purple-600',
29
+ 'from-pink-500 to-rose-600',
30
+ 'from-amber-400 to-orange-500',
31
+ 'from-emerald-500 to-teal-600',
32
+ 'from-sky-500 to-cyan-600',
33
+ 'from-fuchsia-500 to-pink-600',
34
+ 'from-orange-500 to-red-600',
35
+ 'from-indigo-500 to-blue-600',
36
+ 'from-teal-500 to-green-600',
37
+ ];
38
+ // Soft top-highlight + drop shadow → iOS icon depth/gloss.
39
+ const ICON_GLOSS = 'shadow-[0_4px_10px_-2px_rgb(0_0_0/0.25),inset_0_1px_0_0_rgb(255_255_255/0.45)]';
40
+ function hashStr(s) {
41
+ let h = 0;
42
+ for (let i = 0; i < s.length; i++)
43
+ h = (h * 31 + s.charCodeAt(i)) | 0;
44
+ return Math.abs(h);
45
+ }
46
+ export function HomeAppsStrip({ apps, favorites, onOpen, onBrowseMarketplace, isAdmin, }) {
47
+ const { t } = useObjectTranslation();
48
+ const { appLabel } = useObjectLabel();
49
+ const [showAll, setShowAll] = useState(false);
50
+ const favNames = useMemo(() => new Set(favorites.filter((f) => f.id.startsWith('app:')).map((f) => f.id.slice(4))), [favorites]);
51
+ const ordered = useMemo(() => [...apps].sort((a, b) => (favNames.has(b.name) ? 1 : 0) - (favNames.has(a.name) ? 1 : 0)), [apps, favNames]);
52
+ const overflow = ordered.length - COMPACT_LIMIT;
53
+ const visible = showAll ? ordered : ordered.slice(0, COMPACT_LIMIT);
54
+ return (_jsxs("section", { className: "mb-6", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2.5", children: [_jsx("span", { className: "inline-flex h-8 w-8 items-center justify-center rounded-xl border border-border bg-muted text-muted-foreground", children: _jsx(LayoutGrid, { className: "h-4 w-4" }) }), _jsx("h2", { className: "text-base font-semibold tracking-tight", children: t('home.yourApps', { defaultValue: 'Your apps' }) }), _jsx("span", { className: "text-sm text-muted-foreground", children: ordered.length }), isAdmin && (_jsxs(Button, { variant: "ghost", size: "sm", className: "ml-auto h-8 text-muted-foreground", onClick: onBrowseMarketplace, "data-testid": "browse-marketplace-btn", children: [_jsx(Store, { className: "mr-1.5 h-4 w-4" }), t('home.browseMarketplace', { defaultValue: 'Browse App Marketplace' })] }))] }), _jsxs("div", { className: "grid grid-cols-4 gap-1 sm:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10", children: [visible.map((app) => {
55
+ const Icon = getIcon(app.icon);
56
+ const label = appLabel({ name: app.name, label: resolveI18nLabel(app.label, t) });
57
+ const fav = favNames.has(app.name);
58
+ const grad = ICON_GRADIENTS[hashStr(app.name) % ICON_GRADIENTS.length];
59
+ return (_jsxs("button", { type: "button", onClick: () => onOpen(app), className: "group relative flex flex-col items-center gap-2 rounded-xl p-2.5 text-center transition hover:bg-muted/40 active:scale-[0.96]", "data-testid": `app-tile-${app.name}`, children: [_jsxs("span", { className: cn('relative inline-flex h-12 w-12 items-center justify-center rounded-[13px]', 'bg-gradient-to-br text-white transition-transform group-hover:scale-105', ICON_GLOSS, grad), children: [_jsx(Icon, { className: "h-6 w-6" }), fav && (_jsx("span", { className: "absolute -right-1 -top-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-amber-400 ring-2 ring-background", children: _jsx(Star, { className: "h-2.5 w-2.5 fill-white text-white" }) }))] }), _jsx("span", { className: "w-full truncate text-xs font-medium", children: label })] }, app.name));
60
+ }), !showAll && overflow > 0 && (_jsxs("button", { type: "button", onClick: () => setShowAll(true), className: "group flex flex-col items-center gap-2 rounded-xl p-2.5 text-center transition hover:bg-muted/40 active:scale-[0.96]", "data-testid": "apps-show-all", children: [_jsxs("span", { className: "inline-flex h-12 w-12 items-center justify-center rounded-[13px] border border-dashed border-border text-sm font-medium text-muted-foreground transition-colors group-hover:border-foreground/30 group-hover:text-foreground", children: ["+", overflow] }), _jsx("span", { className: "w-full truncate text-xs text-muted-foreground", children: t('home.showMoreApps', { defaultValue: 'More' }) })] }))] }), showAll && overflow > 0 && (_jsx("button", { type: "button", onClick: () => setShowAll(false), className: "mt-2.5 text-xs text-primary hover:underline", children: t('home.showLess', { defaultValue: 'Show less' }) }))] }));
61
+ }
@@ -16,5 +16,5 @@ interface HomeLayoutProps {
16
16
  */
17
17
  userId?: string;
18
18
  }
19
- export declare function HomeLayout({ children, userId }: HomeLayoutProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function HomeLayout({ children, userId }: HomeLayoutProps): React.JSX.Element;
20
20
  export {};
@@ -12,12 +12,14 @@ import { useEffect } from 'react';
12
12
  import { useNavigationContext } from '../../context/NavigationContext';
13
13
  import { AppHeader } from '../../layout/AppHeader';
14
14
  import { useDiscovery } from '@object-ui/react';
15
+ import { useObjectTranslation } from '@object-ui/i18n';
15
16
  // Lightweight FAB stub — the heavy chat chunk graph only downloads on
16
17
  // first hover/click. See ../../layout/ConsoleChatbotFab.tsx.
17
18
  import { ConsoleChatbotFab } from '../../layout/ConsoleChatbotFab';
18
19
  export function HomeLayout({ children, userId }) {
19
20
  const { setContext } = useNavigationContext();
20
21
  const { isAiEnabled } = useDiscovery();
22
+ const { t } = useObjectTranslation();
21
23
  // Render the chatbot whenever AI is reachable. If the developer has explicitly
22
24
  // configured `VITE_AI_BASE_URL`, trust that opt-in even when discovery
23
25
  // reports AI as disabled (e.g. framework started without `--preset full`).
@@ -26,5 +28,5 @@ export function HomeLayout({ children, userId }) {
26
28
  useEffect(() => {
27
29
  setContext('home');
28
30
  }, [setContext]);
29
- return (_jsxs("div", { className: "flex min-h-svh w-full flex-col bg-background", "data-testid": "home-layout", children: [_jsx("header", { className: "sticky top-0 z-30 flex h-14 w-full shrink-0 items-center gap-2 border-b bg-background px-2 sm:px-4", children: _jsx(AppHeader, { variant: "home" }) }), _jsx("main", { className: "flex-1 min-w-0 overflow-auto pb-20 sm:pb-0", children: children }), showChatbot && _jsx(ConsoleChatbotFab, { appLabel: "Workspace", objects: [], userId: userId })] }));
31
+ return (_jsxs("div", { className: "flex min-h-svh w-full flex-col bg-background", "data-testid": "home-layout", children: [_jsx("header", { className: "sticky top-0 z-30 flex h-14 w-full shrink-0 items-center gap-2 border-b bg-background px-2 sm:px-4", children: _jsx(AppHeader, { variant: "home" }) }), _jsx("main", { className: "flex-1 min-w-0 overflow-auto pb-20 sm:pb-0", children: children }), showChatbot && _jsx(ConsoleChatbotFab, { appLabel: t('workspace.default', { defaultValue: 'Workspace' }), objects: [], userId: userId })] }));
30
32
  }
@@ -9,10 +9,9 @@
9
9
  * - Quick actions for creating apps, importing data, etc.
10
10
  * - Recent apps section (from useRecentItems)
11
11
  * - Starred/Favorite apps section (from useFavorites)
12
- * - Empty state guidance for new users
13
12
  * - Responsive grid layout
14
13
  * - i18n support
15
14
  *
16
15
  * @module
17
16
  */
18
- export declare function HomePage(): import("react/jsx-runtime").JSX.Element;
17
+ export declare function HomePage(): import("react").JSX.Element;
@@ -10,24 +10,72 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  * - Quick actions for creating apps, importing data, etc.
11
11
  * - Recent apps section (from useRecentItems)
12
12
  * - Starred/Favorite apps section (from useFavorites)
13
- * - Empty state guidance for new users
14
13
  * - Responsive grid layout
15
14
  * - i18n support
16
15
  *
17
16
  * @module
18
17
  */
19
- import { useMemo } from 'react';
18
+ import { useMemo, useState, useEffect } from 'react';
20
19
  import { useNavigate } from 'react-router-dom';
21
20
  import { useMetadata } from '../../providers/MetadataProvider';
22
21
  import { useRecentItems } from '../../hooks/useRecentItems';
23
22
  import { useFavorites } from '../../hooks/useFavorites';
24
23
  import { useObjectTranslation } from '@object-ui/i18n';
25
24
  import { useAuth, useIsWorkspaceAdmin } from '@object-ui/auth';
26
- import { AppCard } from './AppCard';
27
- import { RecentApps } from './RecentApps';
28
- import { StarredApps } from './StarredApps';
25
+ import { useAgents, isBuildAgent, isAskAgent } from '@object-ui/plugin-chatbot';
26
+ import { HomeAppsStrip } from './HomeAppsStrip';
27
+ import { HomeActionCenter, HomeContinue, HomeActivity } from './HomeRail';
28
+ import { useHomeInbox } from '../../hooks/useHomeInbox';
29
+ import { appRouteSegment } from '../../utils';
29
30
  import { Empty, EmptyTitle, EmptyDescription, Button } from '@object-ui/components';
30
- import { Plus, Settings, Sparkles, Star, Clock, ArrowDown, Store } from 'lucide-react';
31
+ import { Sparkles, ShieldAlert, X, UploadCloud, MessageSquareText } from 'lucide-react';
32
+ import { useMetadataClient } from '../../views/metadata-admin/useMetadata';
33
+ import { usePublishAllDrafts } from '../../preview/usePublishAllDrafts';
34
+ /** Resolve the AI service base, mirroring AiChatPage/ConsoleFloatingChatbot. */
35
+ function resolveAiApiBase() {
36
+ const env = import.meta.env ?? {};
37
+ const fromEnv = env.VITE_AI_BASE_URL;
38
+ if (fromEnv)
39
+ return fromEnv.replace(/\/$/, '');
40
+ const serverUrl = env.VITE_SERVER_URL ?? '';
41
+ return `${serverUrl.replace(/\/$/, '')}/api/v1/ai`;
42
+ }
43
+ /**
44
+ * Which AI home CTAs to surface, driven by the live agent catalog (the single
45
+ * source of truth) — gated PER agent, because the community edition can be in
46
+ * any of three states:
47
+ * - `askAvailable` — a data/query agent (`ask`/`data_chat`) is deployed → "Ask AI".
48
+ * - `buildAvailable` — a build/authoring agent is deployed → "Build with AI".
49
+ * That's a cloud / AI-Studio feature, ABSENT on open-source builds.
50
+ * - `aiEnabled` — any agent at all (AI is on here in some form).
51
+ * All false while the catalog loads or when AI isn't enabled, so nothing
52
+ * flashes and no AI CTA appears where there's no agent to back it.
53
+ */
54
+ function useHomeAiAvailability() {
55
+ const apiBase = useMemo(() => resolveAiApiBase(), []);
56
+ const { agents } = useAgents({ apiBase });
57
+ return {
58
+ aiEnabled: agents.length > 0,
59
+ askAvailable: agents.some((a) => isAskAgent(a.name)),
60
+ buildAvailable: agents.some((a) => isBuildAgent(a.name)),
61
+ };
62
+ }
63
+ /**
64
+ * Home AI call-to-action(s). "Build with AI" only when a build agent is
65
+ * deployed; "Ask AI" only when a data/query agent is deployed. Renders nothing
66
+ * when neither exists (AI off, or only custom agents — those are reachable via
67
+ * the assistant launcher / FAB). `layout="stack"` is used by the empty-state;
68
+ * the hero uses the default inline row. Availability is passed in so the host
69
+ * fetches the catalog once.
70
+ */
71
+ function HomeAiActions({ askAvailable, buildAvailable, navigate, t, layout = 'row', }) {
72
+ if (!askAvailable && !buildAvailable)
73
+ return null;
74
+ const container = layout === 'stack'
75
+ ? 'mt-6 flex flex-col sm:flex-row items-center gap-3'
76
+ : 'flex shrink-0 items-center gap-2';
77
+ return (_jsxs("div", { className: container, children: [buildAvailable && (_jsxs(Button, { onClick: () => navigate('/ai/build'), "data-testid": "home-build-with-ai", children: [_jsx(Sparkles, { className: "mr-2 h-4 w-4" }), t('home.buildWithAI', { defaultValue: 'Build with AI' })] })), askAvailable && (_jsxs(Button, { variant: buildAvailable ? 'outline' : 'default', onClick: () => navigate('/ai/ask'), "data-testid": "home-ask-ai", children: [_jsx(MessageSquareText, { className: "mr-2 h-4 w-4" }), t('home.askAI', { defaultValue: 'Ask AI' })] }))] }));
78
+ }
31
79
  function pickGreetingKey(hour) {
32
80
  if (hour < 5)
33
81
  return 'home.greetingNight';
@@ -40,14 +88,82 @@ function pickGreetingKey(hour) {
40
88
  return 'home.greetingNight';
41
89
  }
42
90
  /**
43
- * Friendly onboarding hint shown above the All Apps grid when the user has
44
- * no starred or recent items yet. Replaces per-section empty states (which
45
- * would flicker as the backend adapter hydrates).
91
+ * Pending-drafts banner closes the AI magic-moment loop. After the metadata
92
+ * assistant drafts objects/views/apps (ADR-0033 draft-gated authoring), nothing
93
+ * is live until the human publishes. Without this, a user who just had AI build
94
+ * their whole system landed back on an empty-looking home with no trace of it
95
+ * and no path to publish. This surfaces the pending drafts and routes to the
96
+ * designer to review + publish. Disappears automatically once published
97
+ * (listDrafts → 0).
98
+ */
99
+ function PendingDraftsBanner({ t }) {
100
+ const client = useMetadataClient();
101
+ const [drafts, setDrafts] = useState([]);
102
+ // Shared one-click publish (also used by the ADR-0037 draft-preview bar):
103
+ // packages via the probed publish-drafts path, orphans by reference, health
104
+ // surfaced in toasts. See usePublishAllDrafts for the full story.
105
+ const { publishAll, publishing } = usePublishAllDrafts(t);
106
+ const count = drafts.length;
107
+ useEffect(() => {
108
+ let cancelled = false;
109
+ Promise.resolve(client.listDrafts?.({}))
110
+ .then((rows) => {
111
+ if (cancelled || !Array.isArray(rows))
112
+ return;
113
+ setDrafts(rows
114
+ .filter((d) => d && typeof d.type === 'string' && typeof d.name === 'string')
115
+ .map((d) => ({ type: d.type, name: d.name })));
116
+ })
117
+ .catch(() => { });
118
+ return () => { cancelled = true; };
119
+ }, [client]);
120
+ const publish = async () => {
121
+ const result = await publishAll();
122
+ if (!result.ok)
123
+ return;
124
+ setDrafts([]);
125
+ // Surface the now-live app — reload so the populated home shows it.
126
+ setTimeout(() => { try {
127
+ window.location.reload();
128
+ }
129
+ catch { /* ignore */ } }, 700);
130
+ };
131
+ if (count <= 0)
132
+ return null;
133
+ return (_jsx("div", { className: "px-4 sm:px-6 lg:px-8 pt-4", children: _jsx("div", { className: "max-w-7xl mx-auto", children: _jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-indigo-300/60 dark:border-indigo-700/50 bg-indigo-50 dark:bg-indigo-950/30 px-4 py-3", children: [_jsx(UploadCloud, { className: "h-5 w-5 shrink-0 text-indigo-600 dark:text-indigo-400" }), _jsx("p", { className: "flex-1 min-w-0 text-sm text-indigo-900 dark:text-indigo-200", children: t('home.pendingDrafts.message', { count, defaultValue: 'You have {{count}} unpublished change(s) — publish to make them live.' }) }), _jsx(Button, { size: "sm", onClick: publish, disabled: publishing, "data-testid": "pending-drafts-publish", children: publishing
134
+ ? t('home.pendingDrafts.publishing', { defaultValue: 'Publishing…' })
135
+ : t('home.pendingDrafts.cta', { defaultValue: 'Publish' }) })] }) }) }));
136
+ }
137
+ /**
138
+ * Dismissible nudge to set a local recovery password — shown when the user
139
+ * signed in via SSO and has no local credential yet. We no longer force this
140
+ * before the first session (it walled off the magic moment); this gentle,
141
+ * one-time reminder preserves instance self-sufficiency without the friction.
46
142
  */
47
- function GettingStartedHint({ t }) {
48
- return (_jsxs("section", { "data-testid": "home-getting-started", className: "relative overflow-hidden rounded-2xl border border-border/60 bg-card/70 backdrop-blur-sm p-6 sm:p-8", children: [_jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-fuchsia-500/5" }), _jsxs("div", { className: "relative flex flex-col sm:flex-row sm:items-center gap-5", children: [_jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [_jsx("span", { className: "inline-flex h-10 w-10 items-center justify-center rounded-lg bg-amber-500/10 ring-1 ring-amber-500/20 text-amber-600 dark:text-amber-400", children: _jsx(Star, { className: "h-5 w-5" }) }), _jsx("span", { className: "inline-flex h-10 w-10 items-center justify-center rounded-lg bg-emerald-500/10 ring-1 ring-emerald-500/20 text-emerald-600 dark:text-emerald-400", children: _jsx(Clock, { className: "h-5 w-5" }) })] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h2", { className: "text-lg font-semibold tracking-tight", children: t('home.gettingStarted.title', { defaultValue: 'Make this home yours' }) }), _jsx("p", { className: "text-sm text-muted-foreground mt-1 max-w-xl", children: t('home.gettingStarted.description', {
49
- defaultValue: 'Star an app to pin it here for one-click access. Anything you open will show up under Recently Accessed automatically.',
50
- }) })] }), _jsxs("div", { className: "flex items-center gap-2 text-xs font-medium text-muted-foreground", children: [_jsx("span", { children: t('home.gettingStarted.cta', { defaultValue: 'Browse all applications' }) }), _jsx(ArrowDown, { className: "h-3.5 w-3.5" })] })] })] }));
143
+ function RecoveryPasswordReminder({ t }) {
144
+ const navigate = useNavigate();
145
+ const { hasLocalPassword } = useAuth();
146
+ const [show, setShow] = useState(false);
147
+ useEffect(() => {
148
+ if (typeof localStorage !== 'undefined' && localStorage.getItem('os:recovery-pw-dismissed') === '1')
149
+ return;
150
+ let cancelled = false;
151
+ Promise.resolve(hasLocalPassword?.())
152
+ .then((has) => { if (!cancelled && has === false)
153
+ setShow(true); })
154
+ .catch(() => { });
155
+ return () => { cancelled = true; };
156
+ }, [hasLocalPassword]);
157
+ const dismiss = () => {
158
+ try {
159
+ localStorage.setItem('os:recovery-pw-dismissed', '1');
160
+ }
161
+ catch { /* ignore */ }
162
+ setShow(false);
163
+ };
164
+ if (!show)
165
+ return null;
166
+ return (_jsx("div", { className: "px-4 sm:px-6 lg:px-8 pt-4", children: _jsx("div", { className: "max-w-7xl mx-auto", children: _jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-amber-300/60 dark:border-amber-700/50 bg-amber-50 dark:bg-amber-950/30 px-4 py-3", children: [_jsx(ShieldAlert, { className: "h-5 w-5 shrink-0 text-amber-600 dark:text-amber-400" }), _jsx("p", { className: "flex-1 min-w-0 text-sm text-amber-900 dark:text-amber-200", children: t('home.recoveryReminder.message', { defaultValue: 'Set a recovery password so you can still sign in if single sign-on is ever unavailable.' }) }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => navigate('/set-password'), "data-testid": "recovery-pw-set", children: t('home.recoveryReminder.cta', { defaultValue: 'Set password' }) }), _jsx("button", { type: "button", onClick: dismiss, "aria-label": t('home.recoveryReminder.dismiss', { defaultValue: 'Dismiss' }), className: "shrink-0 rounded-md p-1 text-amber-700/70 hover:text-amber-900 dark:text-amber-300/70 dark:hover:text-amber-100", children: _jsx(X, { className: "h-4 w-4" }) })] }) }) }));
51
167
  }
52
168
  export function HomePage() {
53
169
  const navigate = useNavigate();
@@ -57,22 +173,34 @@ export function HomePage() {
57
173
  const { favorites } = useFavorites();
58
174
  const { user } = useAuth();
59
175
  const isAdmin = useIsWorkspaceAdmin();
60
- const activeApps = apps.filter((a) => a.active !== false);
176
+ const { pendingApprovalsCount, notifications, activities } = useHomeInbox();
177
+ // AI CTA gating, per agent: "Build with AI" only when a build agent is
178
+ // deployed (cloud / AI Studio); "Ask AI" only when a data agent is; neither
179
+ // when AI isn't enabled. Community builds typically land in the ask-only state.
180
+ const { askAvailable, buildAvailable } = useHomeAiAvailability();
181
+ const activeApps = apps.filter((a) => a.active !== false && a.hidden !== true);
61
182
  const recentApps = recentItems
62
183
  .filter(item => item.type === 'object' || item.type === 'dashboard' || item.type === 'page' || item.type === 'record')
63
184
  .slice(0, 6);
64
- const starredApps = favorites
65
- .filter(item => item.type === 'object' || item.type === 'dashboard' || item.type === 'page' || item.type === 'record')
66
- .slice(0, 8);
67
185
  const greeting = useMemo(() => t(pickGreetingKey(new Date().getHours()), { defaultValue: 'Welcome' }), [t]);
68
186
  const displayName = (user?.name?.trim() || user?.email?.split('@')[0] || '').trim();
69
187
  if (loading) {
70
188
  return (_jsx("div", { className: "flex flex-1 items-center justify-center py-20", children: _jsx("div", { className: "text-muted-foreground", children: t('home.loading', { defaultValue: 'Loading workspace…' }) }) }));
71
189
  }
72
190
  if (activeApps.length === 0) {
73
- return (_jsx("div", { className: "flex flex-1 items-center justify-center p-6", children: _jsxs(Empty, { children: [_jsx(EmptyTitle, { children: t('home.welcome', { defaultValue: 'Welcome to ObjectUI' }) }), _jsx(EmptyDescription, { children: t('home.welcomeDescription', {
74
- defaultValue: 'Get started by creating your first application or configure your system settings.',
75
- }) }), _jsxs("div", { className: "mt-6 flex flex-col sm:flex-row items-center gap-3", children: [_jsxs(Button, { onClick: () => navigate('/create-app'), "data-testid": "create-first-app-btn", children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), t('home.createFirstApp', { defaultValue: 'Create Your First App' })] }), isAdmin && (_jsxs(Button, { variant: "outline", onClick: () => navigate('/apps/setup/system/marketplace'), "data-testid": "browse-marketplace-empty-btn", children: [_jsx(Store, { className: "mr-2 h-4 w-4" }), t('home.browseMarketplace', { defaultValue: 'Browse App Marketplace' })] })), _jsxs(Button, { variant: "outline", onClick: () => navigate('/apps/setup'), "data-testid": "go-to-settings-btn", children: [_jsx(Settings, { className: "mr-2 h-4 w-4" }), t('home.systemSettings', { defaultValue: 'System Settings' })] })] })] }) }));
191
+ return (_jsxs("div", { className: "flex flex-col flex-1", children: [_jsx(PendingDraftsBanner, { t: t }), _jsx(RecoveryPasswordReminder, { t: t }), _jsx("div", { className: "flex flex-1 items-center justify-center p-6", children: isAdmin ? (_jsxs(Empty, { children: [_jsx(EmptyTitle, { children: t('home.welcome', { defaultValue: 'Welcome to ObjectUI' }) }), _jsx(EmptyDescription, { children: buildAvailable
192
+ ? t('home.welcomeAdminDescription', {
193
+ defaultValue: 'Describe your business in one sentence AI generates the objects, screens, APIs and agent tools. Or set things up yourself from the Administration menu on the left.',
194
+ })
195
+ : askAvailable
196
+ ? t('home.welcomeAdminDescriptionNoBuild', {
197
+ defaultValue: 'Set up your first application from the Administration menu on the left. Once you have data, the AI assistant can help you explore it.',
198
+ })
199
+ : t('home.welcomeAdminDescriptionNoAi', {
200
+ defaultValue: 'Set up your first application from the Administration menu on the left.',
201
+ }) }), _jsx(HomeAiActions, { askAvailable: askAvailable, buildAvailable: buildAvailable, navigate: navigate, t: t, layout: "stack" })] })) : (_jsxs(Empty, { children: [_jsx(EmptyTitle, { children: t('home.noAppsTitle', { defaultValue: 'No applications yet' }) }), _jsx(EmptyDescription, { children: t('home.noAppsDescription', {
202
+ defaultValue: 'There are no applications available to you yet. Please contact your workspace administrator.',
203
+ }) })] })) })] }));
76
204
  }
77
- return (_jsxs("div", { className: "relative isolate min-h-full bg-gradient-to-b from-background via-background to-muted/40", children: [_jsxs("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-x-0 top-0 -z-10 h-[28rem] overflow-hidden", children: [_jsx("div", { className: "absolute -top-32 -left-24 h-[28rem] w-[28rem] rounded-full bg-primary/30 blur-3xl opacity-70 dark:opacity-40" }), _jsx("div", { className: "absolute -top-20 right-[-6rem] h-[26rem] w-[36rem] rounded-full bg-sky-400/30 blur-3xl opacity-70 dark:opacity-35" }), _jsx("div", { className: "absolute top-32 left-1/3 h-[18rem] w-[24rem] rounded-full bg-fuchsia-400/25 blur-3xl opacity-60 dark:opacity-25" }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-b from-transparent via-background/40 to-background" })] }), _jsx("section", { className: "px-4 sm:px-6 lg:px-8 pt-10 pb-6", children: _jsxs("div", { className: "max-w-7xl mx-auto", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs font-medium text-muted-foreground mb-3", children: [_jsx(Sparkles, { className: "h-3.5 w-3.5 text-primary" }), _jsx("span", { className: "uppercase tracking-wider", children: t('home.title', { defaultValue: 'Home' }) })] }), _jsxs("h1", { className: "text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight text-pretty", children: [_jsxs("span", { className: "bg-gradient-to-r from-foreground via-foreground to-foreground/70 bg-clip-text text-transparent", children: [greeting, displayName ? `, ${displayName}` : ''] }), _jsx("span", { className: "text-foreground/40", children: "." })] }), _jsx("p", { className: "text-base sm:text-lg text-muted-foreground mt-2 max-w-2xl", children: t('home.heroTagline', { defaultValue: 'Pick up where you left off, or explore something new.' }) })] }) }), _jsx("div", { className: "px-4 sm:px-6 lg:px-8 pb-16", children: _jsxs("div", { className: "max-w-7xl mx-auto space-y-10", children: [starredApps.length === 0 && recentApps.length === 0 && (_jsx(GettingStartedHint, { t: t })), starredApps.length > 0 && _jsx(StarredApps, { items: starredApps }), recentApps.length > 0 && _jsx(RecentApps, { items: recentApps }), _jsxs("section", { children: [_jsxs("div", { className: "flex items-end justify-between mb-5", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: t('home.allApps', { defaultValue: 'All Applications' }) }), _jsxs("p", { className: "text-sm text-muted-foreground mt-1", children: [activeApps.length, ' · ', t('home.stats.apps', { defaultValue: 'Applications' })] })] }), isAdmin && (_jsxs(Button, { variant: "outline", onClick: () => navigate('/apps/setup/system/marketplace'), "data-testid": "browse-marketplace-btn", children: [_jsx(Store, { className: "mr-2 h-4 w-4" }), t('home.browseMarketplace', { defaultValue: 'Browse App Marketplace' })] }))] }), _jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4", children: activeApps.map((app, idx) => (_jsx(AppCard, { app: app, index: idx, onClick: () => navigate(`/apps/${app.name}`), isFavorite: favorites.some(f => f.id === `app:${app.name}`) }, app.name))) })] })] }) })] }));
205
+ return (_jsxs("div", { className: "relative min-h-full bg-background", children: [_jsx(PendingDraftsBanner, { t: t }), _jsx(RecoveryPasswordReminder, { t: t }), _jsx("div", { className: "px-4 sm:px-6 lg:px-8 pt-8 pb-16", children: _jsxs("div", { className: "max-w-7xl mx-auto", children: [_jsxs("div", { className: "mb-7 flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("h1", { className: "text-2xl sm:text-3xl font-bold tracking-tight text-pretty", children: [_jsxs("span", { className: "text-foreground", children: [greeting, displayName ? ', ' : ''] }), displayName && _jsx("span", { className: "text-primary", children: displayName }), _jsx("span", { className: "text-foreground/40", children: "." })] }), _jsx("p", { className: "mt-1 text-sm sm:text-base text-muted-foreground", children: t('home.heroTagline', { defaultValue: 'Pick up where you left off, or explore something new.' }) })] }), _jsx(HomeAiActions, { askAvailable: askAvailable, buildAvailable: buildAvailable, navigate: navigate, t: t })] }), _jsx(HomeAppsStrip, { apps: activeApps, favorites: favorites, onOpen: (app) => navigate(`/apps/${appRouteSegment(app) ?? app.name}`), onBrowseMarketplace: () => navigate('/apps/setup/system/marketplace'), isAdmin: isAdmin }), _jsx("div", { className: "mb-6", children: _jsx(HomeActionCenter, { pendingApprovalsCount: pendingApprovalsCount, notifications: notifications, onOpenApprovals: () => navigate('/apps/setup/system/approvals'), onOpenNotification: (n) => navigate(n.actionUrl || '/apps/setup/sys_inbox_message?view=mine'), t: t }) }), _jsxs("div", { className: "grid grid-cols-1 items-start gap-6 lg:grid-cols-[minmax(0,1fr)_360px]", children: [_jsx(HomeContinue, { items: recentApps, onOpen: (href) => navigate(href), t: t }), _jsx(HomeActivity, { items: activities, onViewAll: () => navigate('/apps/setup/sys_activity'), t: t })] })] }) })] }));
78
206
  }
@@ -0,0 +1,22 @@
1
+ import type { ActivityItem } from '../../layout/ActivityFeed';
2
+ import type { HomeNotification } from '../../hooks/useHomeInbox';
3
+ import type { RecentItem } from '../../hooks/useRecentItems';
4
+ type TFn = (key: string, opts?: any) => string;
5
+ export declare function HomeActionCenter({ pendingApprovalsCount, notifications, onOpenApprovals, onOpenNotification, t, }: {
6
+ pendingApprovalsCount: number;
7
+ notifications: HomeNotification[];
8
+ onOpenApprovals: () => void;
9
+ onOpenNotification: (n: HomeNotification) => void;
10
+ t: TFn;
11
+ }): import("react").JSX.Element;
12
+ export declare function HomeContinue({ items, onOpen, t }: {
13
+ items: RecentItem[];
14
+ onOpen: (href: string) => void;
15
+ t: TFn;
16
+ }): import("react").JSX.Element;
17
+ export declare function HomeActivity({ items, onViewAll, t }: {
18
+ items: ActivityItem[];
19
+ onViewAll: () => void;
20
+ t: TFn;
21
+ }): import("react").JSX.Element;
22
+ export {};