@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,221 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
3
+ /**
4
+ * DatasetDefaultInspector — the curated designer for an analytics `dataset`
5
+ * (ADR-0021). Replaces the generic whole-draft JSON SchemaForm with structured,
6
+ * fool-proof editors for the dataset's parts:
7
+ *
8
+ * - base `object`,
9
+ * - `include` relationships (the join allowlist — D-C),
10
+ * - `dimensions` (name + field/`relationship.field` + type + granularity), and
11
+ * - `measures` (name + aggregate + field + format/currency/derived).
12
+ *
13
+ * The base object, the included relationships, and every `field` are picked
14
+ * from the live object graph (a searchable combo over {@link useDatasetFieldCatalog})
15
+ * — not recalled by hand — so authoring matches mainstream low-code dataset
16
+ * builders. The aggregate / type / granularity are closed dropdowns so an
17
+ * author can't type an unsupported value. Each combo still allows a custom
18
+ * value as an escape hatch (offline catalog, computed path). Edits flow through
19
+ * `onPatch`; the DatasetPreview on the canvas re-runs live as the draft changes.
20
+ */
21
+ import * as React from 'react';
22
+ import { AlertTriangle, ArrowRight, ChevronDown, Plus, Trash2, X } from 'lucide-react';
23
+ import { Badge, Button, FilterBuilder, Label, Popover, PopoverContent, PopoverTrigger } from '@object-ui/components';
24
+ import { InspectorShell, InspectorTextField, InspectorSelectField, InspectorCheckboxField, appendArray, spliceArray, } from './_shared';
25
+ import { InspectorComboField } from './InspectorComboField';
26
+ import { toFieldName } from '../previews/object-fields-io';
27
+ import { formatMeasure } from '@object-ui/core';
28
+ import { conditionToGroup, groupToCondition } from './datasetFilterCondition';
29
+ import { useObjectOptions, useDatasetFieldCatalog, useDatasetUsage, fieldTypeToDimensionType, } from './useDatasetFields';
30
+ // Closed to what the dataset compiler supports (no array_agg/string_agg in v1).
31
+ const AGGREGATE_OPTIONS = [
32
+ { value: 'count', label: 'count' },
33
+ { value: 'sum', label: 'sum' },
34
+ { value: 'avg', label: 'avg' },
35
+ { value: 'min', label: 'min' },
36
+ { value: 'max', label: 'max' },
37
+ { value: 'count_distinct', label: 'count distinct' },
38
+ ];
39
+ const DIMENSION_TYPE_OPTIONS = [
40
+ { value: 'string', label: 'string' },
41
+ { value: 'number', label: 'number' },
42
+ { value: 'date', label: 'date' },
43
+ { value: 'boolean', label: 'boolean' },
44
+ { value: 'lookup', label: 'lookup' },
45
+ ];
46
+ const DATE_GRANULARITY_OPTIONS = [
47
+ { value: '', label: '— none —' },
48
+ { value: 'day', label: 'day' },
49
+ { value: 'week', label: 'week' },
50
+ { value: 'month', label: 'month' },
51
+ { value: 'quarter', label: 'quarter' },
52
+ { value: 'year', label: 'year' },
53
+ ];
54
+ const DERIVED_OP_OPTIONS = [
55
+ { value: 'ratio', label: 'ratio (a ÷ b)' },
56
+ { value: 'sum', label: 'sum (a + b)' },
57
+ { value: 'difference', label: 'difference (a − b)' },
58
+ { value: 'product', label: 'product (a × b)' },
59
+ ];
60
+ // Display-format picker options — a business user shouldn't have to know numeral
61
+ // syntax (`$0,0.00`), so the inspector offers kind + decimals + currency and
62
+ // generates the `format`/`currency` strings.
63
+ const FORMAT_KIND_OPTIONS = [
64
+ { value: 'raw', label: 'Raw number' },
65
+ { value: 'number', label: 'Number — 1,234.5' },
66
+ { value: 'currency', label: 'Currency — $1,234.50' },
67
+ { value: 'percent', label: 'Percent — 12.3%' },
68
+ ];
69
+ const DECIMALS_OPTIONS = [
70
+ { value: '0', label: '0' },
71
+ { value: '1', label: '1' },
72
+ { value: '2', label: '2' },
73
+ ];
74
+ const CURRENCY_OPTIONS = [
75
+ { value: 'USD', label: 'USD ($)' },
76
+ { value: 'EUR', label: 'EUR (€)' },
77
+ { value: 'GBP', label: 'GBP (£)' },
78
+ { value: 'CNY', label: 'CNY (¥)' },
79
+ { value: 'JPY', label: 'JPY (¥)' },
80
+ { value: 'INR', label: 'INR (₹)' },
81
+ { value: 'CAD', label: 'CAD ($)' },
82
+ { value: 'AUD', label: 'AUD ($)' },
83
+ ];
84
+ function SectionHeader({ title, count, onAdd, addLabel }) {
85
+ return (_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: title }), _jsx(Badge, { variant: "outline", className: "text-[10px]", children: count })] }), onAdd && (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "h-6 gap-1 px-1.5 text-[11px]", onClick: onAdd, children: [_jsx(Plus, { className: "h-3 w-3" }), " ", addLabel] }))] }));
86
+ }
87
+ /** Native disclosure for a row's optional / advanced fields. */
88
+ function Advanced({ children }) {
89
+ return (_jsxs("details", { className: "group", children: [_jsx("summary", { className: "cursor-pointer select-none list-none text-[11px] text-muted-foreground hover:text-foreground", children: _jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(ArrowRight, { className: "h-3 w-3 transition-transform group-open:rotate-90" }), "Advanced"] }) }), _jsx("div", { className: "mt-1.5 space-y-1.5 border-l pl-2.5", children: children })] }));
90
+ }
91
+ /** Best-effort parse of a stored measure format into the picker's {kind, decimals}. */
92
+ function parseMeasureFormat(format, currency) {
93
+ const f = (format ?? '').trim();
94
+ const m = f.match(/\.(0+)/);
95
+ const decimals = m ? Math.min(m[1].length, 2) : 0;
96
+ if (currency || /[$£€¥₹]/.test(f))
97
+ return { kind: 'currency', decimals };
98
+ if (f.includes('%'))
99
+ return { kind: 'percent', decimals };
100
+ if (f)
101
+ return { kind: 'number', decimals };
102
+ return { kind: 'raw', decimals: 0 };
103
+ }
104
+ /** Generate {format, currency} from the picker selection. */
105
+ function buildMeasureFormat(kind, decimals, currency) {
106
+ const dp = decimals > 0 ? '.' + '0'.repeat(decimals) : '';
107
+ switch (kind) {
108
+ case 'number': return { format: `0,0${dp}`, currency: undefined };
109
+ case 'currency': return { format: `0,0${dp}`, currency: currency || 'USD' };
110
+ case 'percent': return { format: `0${dp}%`, currency: undefined };
111
+ default: return { format: undefined, currency: undefined };
112
+ }
113
+ }
114
+ /**
115
+ * Structured display-format picker for a measure. Maps {kind, decimals, currency}
116
+ * ⇄ the spec's `format`/`currency` strings and shows a live sample so a business
117
+ * user never has to hand-write a numeral pattern.
118
+ */
119
+ function MeasureFormatField({ measure, onPatch, disabled }) {
120
+ const { kind, decimals } = parseMeasureFormat(measure.format, measure.currency);
121
+ const currency = measure.currency || 'USD';
122
+ const apply = (k, d, c) => onPatch(buildMeasureFormat(k, d, c));
123
+ const sample = formatMeasure(kind === 'percent' ? 0.1234 : 1234.5, measure.format, measure.currency);
124
+ return (_jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "grid grid-cols-2 gap-1.5", children: [_jsx(InspectorSelectField, { label: "Display format", value: kind, options: FORMAT_KIND_OPTIONS, onCommit: (v) => apply(v, decimals, currency), disabled: disabled }), kind !== 'raw' && (_jsx(InspectorSelectField, { label: "Decimals", value: String(decimals), options: DECIMALS_OPTIONS, onCommit: (v) => apply(kind, parseInt(v, 10) || 0, currency), disabled: disabled }))] }), kind === 'currency' && (_jsx(InspectorSelectField, { label: "Currency", value: currency, options: CURRENCY_OPTIONS, onCommit: (v) => apply(kind, decimals, v), disabled: disabled })), kind !== 'raw' && (_jsxs("p", { className: "text-[10px] text-muted-foreground", children: ["Sample: ", _jsx("span", { className: "font-mono tabular-nums", children: sample })] }))] }));
125
+ }
126
+ /** The relationship prefix of a `relationship.field` path that isn't yet in `include`, else null. */
127
+ function missingRelationship(field, include) {
128
+ if (!field || !field.includes('.'))
129
+ return null;
130
+ const rel = field.split('.')[0];
131
+ return rel && !include.includes(rel) ? rel : null;
132
+ }
133
+ /** Inline author-time warning: a `relationship.field` whose join isn't declared in `include`. */
134
+ function RelWarning({ rel, onAdd, disabled }) {
135
+ return (_jsxs("p", { className: "flex items-center gap-1 text-[10px] text-amber-600 dark:text-amber-400", children: [_jsx(AlertTriangle, { className: "h-3 w-3 shrink-0" }), _jsxs("span", { children: ["Relationship ", _jsx("code", { className: "font-mono", children: rel }), " isn't in Included relationships."] }), !disabled && onAdd && (_jsx("button", { type: "button", className: "underline hover:no-underline", onClick: onAdd, children: "Add it" }))] }));
136
+ }
137
+ /**
138
+ * Visual filter editor for a dataset/measure `FilterCondition`. Wraps the shared
139
+ * {@link FilterBuilder} (a flat AND of `field op value` rows) and converts to/from
140
+ * the spec's Mongo-style `FilterCondition`. Filters it can't faithfully edit
141
+ * (nested / `$or` / multi-op) degrade to a "edit in Source" note rather than being
142
+ * silently rewritten. See {@link conditionToGroup} / {@link groupToCondition}.
143
+ */
144
+ function DatasetFilterField({ label, help, value, onCommit, fields, disabled }) {
145
+ const { group, representable } = conditionToGroup(value);
146
+ const count = group.conditions.length;
147
+ return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), !representable ? (_jsxs("p", { className: "rounded-md border border-dashed bg-muted/30 px-2.5 py-1.5 text-[11px] text-muted-foreground", children: ["Advanced filter (nested / OR) \u2014 edit it in the ", _jsx("span", { className: "font-medium", children: "Source" }), " tab."] })) : (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: disabled, className: "h-8 w-full justify-between text-xs font-normal", children: [_jsx("span", { className: "truncate text-left", children: count ? `${count} condition${count === 1 ? '' : 's'}` : _jsx("span", { className: "text-muted-foreground", children: "+ Add filter\u2026" }) }), _jsx(ChevronDown, { className: "h-3.5 w-3.5 opacity-60 shrink-0" })] }) }), _jsx(PopoverContent, { align: "start", className: "w-[440px] max-w-[90vw] p-3", children: fields.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground", children: "Pick a base object to add filter conditions." })) : (_jsx(FilterBuilder, { fields: fields, value: group, onChange: (g) => onCommit(groupToCondition(g)) })) })] })), help && _jsx("p", { className: "text-[10px] text-muted-foreground", children: help })] }));
148
+ }
149
+ export function DatasetDefaultInspector({ draft, onPatch, readOnly, name }) {
150
+ const label = typeof draft.label === 'string' ? draft.label : '';
151
+ const description = typeof draft.description === 'string' ? draft.description : '';
152
+ const object = typeof draft.object === 'string' ? draft.object : '';
153
+ const include = Array.isArray(draft.include) ? draft.include : [];
154
+ const dimensions = Array.isArray(draft.dimensions) ? draft.dimensions : [];
155
+ const measures = Array.isArray(draft.measures) ? draft.measures : [];
156
+ const datasetName = typeof draft.name === 'string' ? draft.name : undefined;
157
+ // In create mode the host passes an empty `name` (the PK is assigned on first
158
+ // save). Mirror ReportDefaultInspector: expose an editable Name that auto-
159
+ // derives a snake_case slug from the label until the author edits it directly,
160
+ // so a dataset created through the canvas saves with a valid identifier instead
161
+ // of dead-ending on the empty-name identity rule.
162
+ const createMode = !name;
163
+ const nameTouched = React.useRef(false);
164
+ const nameValue = typeof draft.name === 'string' ? draft.name : '';
165
+ const { options: objectOptions, loading: objectsLoading } = useObjectOptions();
166
+ const { relationships, fieldOptions, loading: catalogLoading } = useDatasetFieldCatalog(object, include);
167
+ const usage = useDatasetUsage(datasetName);
168
+ const objectComboOptions = React.useMemo(() => objectOptions.map((o) => ({ value: o.name, label: o.label })), [objectOptions]);
169
+ const relationshipComboOptions = React.useMemo(() => relationships.map((r) => ({ value: r.name, label: r.label, hint: r.referenceTo ? `→ ${r.referenceTo}` : undefined })), [relationships]);
170
+ const fieldComboOptions = React.useMemo(() => fieldOptions.map((f) => ({ value: f.value, label: f.label, hint: f.type, group: f.group })), [fieldOptions]);
171
+ // Base-object fields for the filter builders (scope + measure filters operate on
172
+ // the base table; relationship-path filters are out of scope for v1).
173
+ const filterFields = React.useMemo(() => fieldOptions.filter((f) => !f.value.includes('.')).map((f) => ({ value: f.value, label: f.label, type: f.type })), [fieldOptions]);
174
+ const datasetFilter = draft.filter && typeof draft.filter === 'object' ? draft.filter : undefined;
175
+ const baseLabel = objectComboOptions.find((o) => o.value === object)?.label ?? object;
176
+ const patchDimension = (i, patch) => onPatch({ dimensions: dimensions.map((d, idx) => (idx === i ? { ...d, ...patch } : d)) });
177
+ const patchMeasure = (i, patch) => onPatch({ measures: measures.map((m, idx) => (idx === i ? { ...m, ...patch } : m)) });
178
+ // Picking a field auto-infers the dimension type from the field's framework
179
+ // type (region:string, close_date:date, …) — the BI "pick field, type follows"
180
+ // convention — while leaving the Type select free to override.
181
+ const leafName = (path) => (path.includes('.') ? path.split('.').pop() ?? path : path);
182
+ const pickDimensionField = (i, v) => {
183
+ const opt = fieldOptions.find((o) => o.value === v);
184
+ const patch = opt?.type ? { field: v, type: fieldTypeToDimensionType(opt.type) } : { field: v };
185
+ if (!dimensions[i]?.name)
186
+ patch.name = leafName(v); // auto-name from field when unnamed
187
+ patchDimension(i, patch);
188
+ };
189
+ const pickMeasureField = (i, v) => {
190
+ const patch = { field: v };
191
+ if (!measures[i]?.name)
192
+ patch.name = leafName(v); // auto-name from field when unnamed
193
+ patchMeasure(i, patch);
194
+ };
195
+ return (_jsxs(InspectorShell, { kindLabel: "Dataset", title: String(label || draft.name || 'Dataset'), onClose: () => { }, hideClose: true, children: [datasetName && !usage.loading && (_jsx("p", { className: usage.reports + usage.dashboards > 0
196
+ ? 'rounded-md border border-amber-500/30 bg-amber-500/5 px-2.5 py-1.5 text-[11px] text-amber-700 dark:text-amber-300'
197
+ : 'text-[11px] text-muted-foreground', children: usage.reports + usage.dashboards > 0
198
+ ? `Bound by ${usage.reports} report${usage.reports === 1 ? '' : 's'} · ${usage.dashboards} dashboard${usage.dashboards === 1 ? '' : 's'} — changes affect them.`
199
+ : 'Not yet bound by any report or dashboard.' })), createMode && (_jsx(InspectorTextField, { label: "Name", value: nameValue, onCommit: (v) => { nameTouched.current = true; onPatch({ name: toFieldName(v) }); }, placeholder: "snake_case identifier", disabled: readOnly, mono: true })), _jsx(InspectorTextField, { label: "Label", value: label, onCommit: (v) => {
200
+ // Live-derive the snake_case name from the label until the author edits
201
+ // the Name field directly (create mode only).
202
+ const patch = { label: v };
203
+ if (createMode && !nameTouched.current)
204
+ patch.name = toFieldName(v);
205
+ onPatch(patch);
206
+ }, disabled: readOnly }), _jsx(InspectorTextField, { label: "Description", value: description, onCommit: (v) => onPatch({ description: v }), disabled: readOnly }), _jsx(InspectorComboField, { label: "Base object", value: object, onCommit: (v) => onPatch({ object: v }), options: objectComboOptions, loading: objectsLoading, placeholder: "Select an object\u2026", searchPlaceholder: "Search objects\u2026", disabled: readOnly, mono: true }), _jsxs("div", { className: "border-t pt-3 space-y-1.5", children: [_jsx(SectionHeader, { title: "Included relationships", count: include.length, addLabel: "Add", onAdd: readOnly ? undefined : () => onPatch({ include: appendArray(include, '') }) }), include.length === 0 ? (_jsxs("p", { className: "rounded-md border border-dashed bg-muted/30 px-3 py-2 text-center text-[11px] text-muted-foreground", children: ["No joins. Add a relationship (a lookup field on ", _jsx("code", { children: baseLabel || 'the base object' }), ") to use ", _jsx("code", { children: "relationship.field" }), " dimensions/measures."] })) : (include.map((rel, i) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(InspectorComboField, { value: rel, onCommit: (v) => onPatch({ include: include.map((r, idx) => (idx === i ? v : r)) }), options: relationshipComboOptions, loading: catalogLoading, placeholder: "Select a relationship\u2026", searchPlaceholder: "Search relationships\u2026", disabled: readOnly, mono: true }), !readOnly && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7 w-7 shrink-0 p-0", onClick: () => onPatch({ include: spliceArray(include, i, null) }), "aria-label": "Remove relationship", children: _jsx(X, { className: "h-3.5 w-3.5" }) }))] }, i)))), object && include.length > 0 && (_jsxs("div", { className: "flex flex-wrap items-center gap-x-1 gap-y-0.5 pt-0.5 text-[10px] text-muted-foreground", children: [_jsx("span", { className: "font-mono font-medium", children: baseLabel }), include.map((rel, i) => {
207
+ const r = relationships.find((x) => x.name === rel);
208
+ return (_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(ArrowRight, { className: "h-3 w-3 opacity-60" }), _jsxs("span", { className: "font-mono", children: [rel, r?.referenceTo ? ` (${r.referenceTo})` : ''] })] }, i));
209
+ })] }))] }), _jsx("div", { className: "border-t pt-3", children: _jsx(DatasetFilterField, { label: "Scope filter", help: "Intrinsic scope, ANDed into every query (e.g. exclude soft-deleted records).", value: datasetFilter, onCommit: (fc) => onPatch({ filter: fc }), fields: filterFields, disabled: readOnly }) }), _jsxs("div", { className: "border-t pt-3 space-y-2", children: [_jsx(SectionHeader, { title: "Dimensions", count: dimensions.length, addLabel: "Add dimension", onAdd: readOnly ? undefined : () => onPatch({ dimensions: appendArray(dimensions, { name: '', field: '', type: 'string' }) }) }), dimensions.map((d, i) => (_jsxs("div", { className: "rounded-md border p-2 space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("span", { className: "text-[11px] font-medium text-muted-foreground", children: ["Dimension ", i + 1] }), !readOnly && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": "Remove dimension", title: "Remove dimension", className: "h-6 w-6 shrink-0 p-0 text-muted-foreground hover:text-destructive", onClick: () => onPatch({ dimensions: spliceArray(dimensions, i, null) }), children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }))] }), _jsx(InspectorTextField, { label: "Name", value: d.name ?? '', onCommit: (v) => patchDimension(i, { name: v }), placeholder: "e.g. region", disabled: readOnly, mono: true }), _jsx(InspectorComboField, { label: "Field", value: d.field ?? '', onCommit: (v) => pickDimensionField(i, v), options: fieldComboOptions, loading: catalogLoading, placeholder: "field or relationship.field", searchPlaceholder: "Search fields\u2026", disabled: readOnly, mono: true }), (() => { const rel = missingRelationship(d.field, include); return rel ? _jsx(RelWarning, { rel: rel, disabled: readOnly, onAdd: () => onPatch({ include: appendArray(include, rel) }) }) : null; })(), _jsx(InspectorSelectField, { label: "Type", value: d.type, options: DIMENSION_TYPE_OPTIONS, onCommit: (v) => patchDimension(i, { type: v }), disabled: readOnly }), _jsxs(Advanced, { children: [_jsx(InspectorTextField, { label: "Label (optional)", value: d.label ?? '', onCommit: (v) => patchDimension(i, { label: v || undefined }), placeholder: d.name || 'Display label', disabled: readOnly }), d.type === 'date' && (_jsx(InspectorSelectField, { label: "Date bucket", value: d.dateGranularity ?? '', options: DATE_GRANULARITY_OPTIONS, onCommit: (v) => patchDimension(i, { dateGranularity: v || undefined }), disabled: readOnly }))] })] }, i)))] }), _jsxs("div", { className: "border-t pt-3 space-y-2", children: [_jsx(SectionHeader, { title: "Measures", count: measures.length, addLabel: "Add measure", onAdd: readOnly ? undefined : () => onPatch({ measures: appendArray(measures, { name: '', aggregate: 'sum', field: '' }) }) }), measures.map((m, i) => {
210
+ const otherMeasures = measures.filter((_, idx) => idx !== i).map((x) => x.name).filter((n) => !!n);
211
+ const derived = m.derived;
212
+ return (_jsxs("div", { className: "rounded-md border p-2 space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("span", { className: "text-[11px] font-medium text-muted-foreground", children: ["Measure ", i + 1] }), !readOnly && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": "Remove measure", title: "Remove measure", className: "h-6 w-6 shrink-0 p-0 text-muted-foreground hover:text-destructive", onClick: () => onPatch({ measures: spliceArray(measures, i, null) }), children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }))] }), _jsx(InspectorTextField, { label: "Name", value: m.name ?? '', onCommit: (v) => patchMeasure(i, { name: v }), placeholder: "e.g. revenue", disabled: readOnly, mono: true }), _jsx(InspectorSelectField, { label: "Aggregate", value: m.aggregate, options: AGGREGATE_OPTIONS, onCommit: (v) => patchMeasure(i, { aggregate: v }), disabled: readOnly }), _jsx(InspectorComboField, { label: "Field", value: m.field ?? '', onCommit: (v) => pickMeasureField(i, v), options: fieldComboOptions, loading: catalogLoading, placeholder: "field (optional for count)", searchPlaceholder: "Search fields\u2026", disabled: readOnly, mono: true }), (() => { const rel = missingRelationship(m.field, include); return rel ? _jsx(RelWarning, { rel: rel, disabled: readOnly, onAdd: () => onPatch({ include: appendArray(include, rel) }) }) : null; })(), _jsxs(Advanced, { children: [_jsx(InspectorTextField, { label: "Label (optional)", value: m.label ?? '', onCommit: (v) => patchMeasure(i, { label: v || undefined }), placeholder: m.name || 'Display label', disabled: readOnly }), _jsx(MeasureFormatField, { measure: m, onPatch: (pp) => patchMeasure(i, pp), disabled: readOnly }), _jsx(DatasetFilterField, { label: "Filter (measure-scoped)", help: "Only rows matching this filter feed this measure (e.g. won_amount = sum(amount) where stage = won).", value: m.filter, onCommit: (fc) => patchMeasure(i, { filter: fc }), fields: filterFields, disabled: readOnly }), _jsx(InspectorCheckboxField, { label: "Derived \u2014 computed from other measures", value: !!derived, onCommit: (v) => patchMeasure(i, { derived: v ? { op: 'ratio', of: [] } : undefined }), disabled: readOnly }), derived && (_jsxs("div", { className: "space-y-1.5 rounded-md border border-dashed p-2", children: [_jsx(InspectorSelectField, { label: "Operation", value: derived.op, options: DERIVED_OP_OPTIONS, onCommit: (v) => patchMeasure(i, { derived: { ...derived, op: v } }), disabled: readOnly }), _jsx(Label, { className: "text-xs text-muted-foreground", children: "Operands (other measures)" }), (() => { const need = derived.op === 'ratio' || derived.op === 'difference' ? 2 : 1; const have = Array.isArray(derived.of) ? derived.of.length : 0; return have < need ? _jsxs("p", { className: "text-[10px] text-amber-600 dark:text-amber-400", children: ["Select ", need === 2 ? 'exactly 2 measures' : 'at least 1 measure', " for ", derived.op, "."] }) : null; })(), otherMeasures.length === 0 ? (_jsx("p", { className: "text-[11px] italic text-muted-foreground", children: "Add other measures first." })) : (_jsx("div", { className: "space-y-1", children: otherMeasures.map((nm) => {
213
+ const checked = Array.isArray(derived.of) && derived.of.includes(nm);
214
+ return (_jsx(InspectorCheckboxField, { label: nm, value: checked, disabled: readOnly, onCommit: (v) => {
215
+ const current = Array.isArray(derived.of) ? derived.of : [];
216
+ const next = v ? [...current, nm] : current.filter((x) => x !== nm);
217
+ patchMeasure(i, { derived: { ...derived, of: next } });
218
+ } }, nm));
219
+ }) }))] }))] })] }, i));
220
+ })] })] }));
221
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * FlowEdgeInspector — scoped editor for the selected flow connection (edge).
3
+ *
4
+ * Selection shape: { kind: 'edge', id: <edgeKey> }
5
+ * Patches: draft.edges[i] = {...edge, ...updates}
6
+ *
7
+ * An edge carries the flow's routing semantics between two nodes: an optional
8
+ * branch `label` (e.g. an Approval node's `approve` / `reject` out-edge, a
9
+ * Decision branch name), a guard `condition` (a CEL expression the engine
10
+ * evaluates to pick the branch), and an `isDefault` flag marking the fallback
11
+ * ("else") branch. Source / target are shown read-only — rewiring is done on
12
+ * the canvas, not here — so the edge's identity key stays stable across edits.
13
+ */
14
+ import * as React from 'react';
15
+ import type { MetadataInspectorProps } from '../inspector-registry';
16
+ export declare function FlowEdgeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }: MetadataInspectorProps): React.JSX.Element;
@@ -0,0 +1,126 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { t } from '../i18n';
3
+ import { InspectorShell, InspectorTextField, InspectorSelectField, InspectorCheckboxField, InspectorRemoveButton, InspectorEmptyState, spliceArray, } from './_shared';
4
+ import { Label } from '@object-ui/components';
5
+ import { edgeKey, conditionText } from '../previews/flow-canvas-layout';
6
+ import { validateExpressionClient } from './expression-validate';
7
+ /** Read-only display of an edge endpoint (source / target node id). */
8
+ function EndpointRow({ label, value }) {
9
+ return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsx("div", { className: "flex h-8 items-center rounded border bg-muted/30 px-2 font-mono text-sm text-muted-foreground", children: value })] }));
10
+ }
11
+ export function FlowEdgeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }) {
12
+ const edges = Array.isArray(draft.edges) ? draft.edges : [];
13
+ const index = edges.findIndex((e, i) => edgeKey(e, i) === selection.id);
14
+ const edge = index >= 0 ? edges[index] : null;
15
+ if (!edge) {
16
+ return (_jsx(InspectorShell, { kindLabel: t('engine.inspector.flowEdge.kind', locale), title: selection.label ?? selection.id, onClose: onClearSelection, closeLabel: t('engine.inspector.flowEdge.close', locale), children: _jsx(InspectorEmptyState, { message: t('engine.inspector.flowEdge.missing', locale) }) }));
17
+ }
18
+ // Splice an updated edge in place. A field edit never moves the edge in the
19
+ // array, so the row index is stable; but an edge without an explicit `id`
20
+ // keys off `source->target#index`, so we re-point the selection to the fresh
21
+ // key after the patch to keep the panel attached to the same edge.
22
+ const patchEdge = (updates) => {
23
+ const next = { ...edge, ...updates };
24
+ // Prune empty optional keys so a cleared field doesn't linger in the draft.
25
+ for (const k of ['label', 'condition', 'isDefault']) {
26
+ const v = next[k];
27
+ if (v === undefined || v === '' || v === false)
28
+ delete next[k];
29
+ }
30
+ // `type` defaults to 'default' (FlowEdgeSchema) — don't persist the noise so
31
+ // a normal edge stays `{ source, target }`; only `back`/`fault`/`conditional`
32
+ // are written.
33
+ if (next.type === 'default' || next.type === '' || next.type === undefined)
34
+ delete next.type;
35
+ onPatch({ edges: spliceArray(edges, index, next) });
36
+ };
37
+ const isDefault = edge.isDefault === true;
38
+ // Decision out-edges can bind EXPLICITLY to one of the source decision's
39
+ // branches (vs the implicit by-order auto-wire): picking a branch writes its
40
+ // expression / label (or marks the default) onto this edge, so routing stays
41
+ // correct even when edges are connected out of branch order.
42
+ const nodes = Array.isArray(draft.nodes)
43
+ ? (draft.nodes)
44
+ : [];
45
+ const sourceNode = nodes.find((n) => n.id === edge.source);
46
+ const branches = sourceNode?.type === 'decision' &&
47
+ Array.isArray(sourceNode.config?.conditions)
48
+ ? (sourceNode.config.conditions)
49
+ : [];
50
+ const branchExpr = (b) => (typeof b.expression === 'string' ? b.expression.trim() : '');
51
+ const branchName = (b) => (typeof b.label === 'string' ? b.label.trim() : '');
52
+ // Which branch this edge currently represents: the default edge maps to the
53
+ // `true`/empty branch; otherwise match by condition, then by label. '' = custom.
54
+ const selectedBranch = (() => {
55
+ if (!branches.length)
56
+ return '';
57
+ if (isDefault) {
58
+ const i = branches.findIndex((b) => { const e = branchExpr(b); return e === '' || e === 'true'; });
59
+ return i >= 0 ? String(i) : '';
60
+ }
61
+ const cond = conditionText(edge.condition);
62
+ let i = cond ? branches.findIndex((b) => branchExpr(b) === cond) : -1;
63
+ if (i < 0 && edge.label)
64
+ i = branches.findIndex((b) => branchName(b) === edge.label);
65
+ return i >= 0 ? String(i) : '';
66
+ })();
67
+ const applyBranch = (key) => {
68
+ if (key === '')
69
+ return; // keep current custom values
70
+ const b = branches[Number(key)];
71
+ if (!b)
72
+ return;
73
+ const expr = branchExpr(b);
74
+ const lbl = branchName(b) || undefined;
75
+ if (expr === '' || expr === 'true')
76
+ patchEdge({ isDefault: true, condition: undefined, label: lbl });
77
+ else
78
+ patchEdge({ isDefault: false, condition: expr, label: lbl });
79
+ };
80
+ // Approval out-edges (ADR-0019/0044) route by branch *label*: the engine
81
+ // resumes down the out-edge whose label matches the decision — `approve` /
82
+ // `reject`, or `revise` (ADR-0044 send-back-for-revision). Offer those as a
83
+ // picker (mirrors APPROVAL_BRANCH_LABELS in @objectstack/spec) so the author
84
+ // need not recall the exact keyword; a free-text label is still allowed.
85
+ const isApprovalSource = sourceNode?.type === 'approval';
86
+ const APPROVAL_BRANCHES = ['approve', 'reject', 'revise'];
87
+ const currentApprovalBranch = (() => {
88
+ const l = (edge.label ?? '').trim().toLowerCase();
89
+ return APPROVAL_BRANCHES.includes(l) ? l : '';
90
+ })();
91
+ const edgeType = (typeof edge.type === 'string' && edge.type) || 'default';
92
+ return (_jsxs(InspectorShell, { kindLabel: t('engine.inspector.flowEdge.kind', locale), title: selection.label ?? `${edge.source} → ${edge.target}`, onClose: onClearSelection, closeLabel: t('engine.inspector.flowEdge.close', locale), footer: _jsx(InspectorRemoveButton, { label: t('engine.inspector.flowEdge.remove', locale), onClick: () => {
93
+ onPatch({ edges: spliceArray(edges, index, null) });
94
+ onClearSelection();
95
+ }, disabled: readOnly }), children: [_jsx(EndpointRow, { label: t('engine.inspector.flowEdge.source', locale), value: edge.source }), _jsx(EndpointRow, { label: t('engine.inspector.flowEdge.target', locale), value: edge.target }), _jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: t('engine.inspector.flowEdge.routing', locale) }), _jsx("span", { className: "h-px flex-1 bg-border", "aria-hidden": true })] }), branches.length > 0 && (_jsx(InspectorSelectField, { label: t('engine.inspector.flowEdge.branch', locale), value: selectedBranch, options: [
96
+ ...branches.map((b, i) => {
97
+ const expr = branchExpr(b);
98
+ const nm = branchName(b) || `Branch ${i + 1}`;
99
+ const suffix = expr === '' || expr === 'true' ? ' \u00b7 default' : ` \u00b7 ${expr}`;
100
+ return { value: String(i), label: `${nm}${suffix}` };
101
+ }),
102
+ { value: '', label: '\u2014 Custom \u2014' },
103
+ ], onCommit: applyBranch, disabled: readOnly })), isApprovalSource && (_jsx(InspectorSelectField, { label: t('engine.inspector.flowEdge.approvalBranch', locale), value: currentApprovalBranch, options: [
104
+ { value: 'approve', label: t('engine.inspector.flowEdge.branchApprove', locale) },
105
+ { value: 'reject', label: t('engine.inspector.flowEdge.branchReject', locale) },
106
+ { value: 'revise', label: t('engine.inspector.flowEdge.branchRevise', locale) },
107
+ { value: '', label: t('engine.inspector.flowEdge.branchCustom', locale) },
108
+ ],
109
+ // Picking a branch writes the matching label; "Custom" keeps the
110
+ // free-text label the author typed below.
111
+ onCommit: (v) => { if (v)
112
+ patchEdge({ label: v }); }, disabled: readOnly })), _jsx(InspectorTextField, { label: t('engine.inspector.flowEdge.label', locale), value: edge.label ?? '', onCommit: (v) => patchEdge({ label: v }), placeholder: t('engine.inspector.flowEdge.labelHint', locale), disabled: readOnly || isDefault }), _jsx(InspectorTextField, { label: t('engine.inspector.flowEdge.condition', locale), value: conditionText(edge.condition) ?? '', onCommit: (v) => patchEdge({ condition: v || undefined }), placeholder: t('engine.inspector.flowEdge.conditionHint', locale), disabled: readOnly || isDefault, mono: true }), (() => {
113
+ // ADR-0032 — flag a malformed edge guard (e.g. `{record.x}` brace-in-CEL)
114
+ // inline, with the same corrective message as build/agent validation.
115
+ const issue = isDefault ? null : validateExpressionClient('predicate', edge.condition);
116
+ return issue ? (_jsx("p", { className: "text-[11px] leading-snug text-destructive", role: "alert", children: issue.message })) : null;
117
+ })(), _jsx(InspectorCheckboxField, { label: t('engine.inspector.flowEdge.isDefault', locale), value: isDefault,
118
+ // The default ("else") branch is taken when no other guard matches, so
119
+ // it carries neither a condition nor a branch label — clear both.
120
+ onCommit: (v) => patchEdge(v ? { isDefault: true, condition: undefined, label: undefined } : { isDefault: false }), disabled: readOnly }), _jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: t('engine.inspector.flowEdge.hint', locale) }), _jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: t('engine.inspector.flowEdge.connection', locale) }), _jsx("span", { className: "h-px flex-1 bg-border", "aria-hidden": true })] }), _jsx(InspectorSelectField, { label: t('engine.inspector.flowEdge.type', locale), value: edgeType, options: [
121
+ { value: 'default', label: t('engine.inspector.flowEdge.typeDefault', locale) },
122
+ { value: 'conditional', label: t('engine.inspector.flowEdge.typeConditional', locale) },
123
+ { value: 'fault', label: t('engine.inspector.flowEdge.typeFault', locale) },
124
+ { value: 'back', label: t('engine.inspector.flowEdge.typeBack', locale) },
125
+ ], onCommit: (v) => patchEdge({ type: v }), disabled: readOnly }), edge.type === 'back' && (_jsx("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", role: "note", children: t('engine.inspector.flowEdge.backHint', locale) }))] }));
126
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * FlowInspector — the single inspector registered for the `flow` metadata type.
3
+ *
4
+ * The flow canvas emits two kinds of selection (see `FlowPreview` /
5
+ * `FlowCanvas`): a node (`{ kind: 'node' }`) or a connection edge
6
+ * (`{ kind: 'edge' }`). This thin router forwards each to its focused editor so
7
+ * neither component has to know about the other. Anything else falls through to
8
+ * the node inspector (which renders an empty-state for an unknown id).
9
+ */
10
+ import * as React from 'react';
11
+ import type { MetadataInspectorProps } from '../inspector-registry';
12
+ export declare function FlowInspector(props: MetadataInspectorProps): React.JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { FlowNodeInspector } from './FlowNodeInspector';
3
+ import { FlowEdgeInspector } from './FlowEdgeInspector';
4
+ export function FlowInspector(props) {
5
+ if (props.selection.kind === 'edge') {
6
+ return _jsx(FlowEdgeInspector, { ...props });
7
+ }
8
+ return _jsx(FlowNodeInspector, { ...props });
9
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * FlowKeyValueField — a small repeatable key/value editor for object-map
3
+ * config (e.g. an action's `params`, a subflow's `input`, request `headers`).
4
+ *
5
+ * Design notes (why local draft state instead of commit-on-keystroke):
6
+ * - The host inspector owns the draft and re-renders from the top on every
7
+ * `onPatch`. Committing each keystroke would rehydrate rows mid-edit and
8
+ * drop focus / collapse half-typed keys. So rows live in LOCAL state and
9
+ * only flush to `onCommit` on blur, Enter, add, or remove.
10
+ * - Rows carry a STABLE `id` (not the editable key) so renaming a key never
11
+ * remounts the row — caret and focus are preserved.
12
+ * - Values are smart-parsed on commit (number / boolean / else string) so an
13
+ * author can type `3` or `true` without writing JSON. Empty and duplicate
14
+ * keys are skipped when flushing (last non-empty wins is avoided — earlier
15
+ * rows take precedence).
16
+ */
17
+ import * as React from 'react';
18
+ export interface FlowKeyValueFieldProps {
19
+ label: string;
20
+ value: unknown;
21
+ onCommit: (value: Record<string, unknown> | undefined) => void;
22
+ disabled?: boolean;
23
+ help?: string;
24
+ addLabel: string;
25
+ keyLabel: string;
26
+ valueLabel: string;
27
+ removeLabel: string;
28
+ emptyLabel: string;
29
+ }
30
+ export declare function FlowKeyValueField({ label, value, onCommit, disabled, help, addLabel, keyLabel, valueLabel, removeLabel, emptyLabel, }: FlowKeyValueFieldProps): React.JSX.Element;
@@ -0,0 +1,125 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
3
+ /**
4
+ * FlowKeyValueField — a small repeatable key/value editor for object-map
5
+ * config (e.g. an action's `params`, a subflow's `input`, request `headers`).
6
+ *
7
+ * Design notes (why local draft state instead of commit-on-keystroke):
8
+ * - The host inspector owns the draft and re-renders from the top on every
9
+ * `onPatch`. Committing each keystroke would rehydrate rows mid-edit and
10
+ * drop focus / collapse half-typed keys. So rows live in LOCAL state and
11
+ * only flush to `onCommit` on blur, Enter, add, or remove.
12
+ * - Rows carry a STABLE `id` (not the editable key) so renaming a key never
13
+ * remounts the row — caret and focus are preserved.
14
+ * - Values are smart-parsed on commit (number / boolean / else string) so an
15
+ * author can type `3` or `true` without writing JSON. Empty and duplicate
16
+ * keys are skipped when flushing (last non-empty wins is avoided — earlier
17
+ * rows take precedence).
18
+ */
19
+ import * as React from 'react';
20
+ import { Plus, X } from 'lucide-react';
21
+ import { Button, Input, Label } from '@object-ui/components';
22
+ import { uniqueId } from './_shared';
23
+ function isPlainObject(v) {
24
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
25
+ }
26
+ /** Render a stored value as an editable string. */
27
+ function toRaw(v) {
28
+ if (v == null)
29
+ return '';
30
+ if (typeof v === 'string')
31
+ return v;
32
+ if (typeof v === 'number' || typeof v === 'boolean')
33
+ return String(v);
34
+ return JSON.stringify(v);
35
+ }
36
+ /** Smart-parse an edited value string back to a scalar (no hand-written JSON). */
37
+ function parseValue(raw) {
38
+ const s = raw.trim();
39
+ if (s === '')
40
+ return '';
41
+ if (s === 'true')
42
+ return true;
43
+ if (s === 'false')
44
+ return false;
45
+ if (/^-?\d+(\.\d+)?$/.test(s))
46
+ return Number(s);
47
+ // Round-trip non-scalar values losslessly: a filter operator like
48
+ // `{"$ne": null}` or an array must parse back to its object/array form, not
49
+ // be flattened to a string. Template refs like `{leadId}` are not valid JSON
50
+ // and correctly fall through to a plain string.
51
+ if ((s.startsWith('{') && s.endsWith('}')) || (s.startsWith('[') && s.endsWith(']'))) {
52
+ try {
53
+ return JSON.parse(s);
54
+ }
55
+ catch {
56
+ return raw;
57
+ }
58
+ }
59
+ return raw;
60
+ }
61
+ function toRows(obj, existingIds) {
62
+ const ids = [...existingIds];
63
+ return Object.entries(obj).map(([key, value]) => {
64
+ const id = uniqueId('kv', ids);
65
+ ids.push(id);
66
+ return { id, key, raw: toRaw(value) };
67
+ });
68
+ }
69
+ /** Flush rows to an object, skipping empty/duplicate keys (first wins). */
70
+ function rowsToObject(rows) {
71
+ const out = {};
72
+ for (const r of rows) {
73
+ const k = r.key.trim();
74
+ if (!k || k in out)
75
+ continue;
76
+ out[k] = parseValue(r.raw);
77
+ }
78
+ return out;
79
+ }
80
+ function serialize(obj) {
81
+ const sorted = Object.keys(obj).sort().reduce((acc, k) => {
82
+ acc[k] = obj[k];
83
+ return acc;
84
+ }, {});
85
+ return JSON.stringify(sorted);
86
+ }
87
+ export function FlowKeyValueField({ label, value, onCommit, disabled, help, addLabel, keyLabel, valueLabel, removeLabel, emptyLabel, }) {
88
+ const external = isPlainObject(value) ? value : {};
89
+ const [rows, setRows] = React.useState(() => toRows(external, []));
90
+ // Track the last value we committed so an external change (node switch) can
91
+ // resync rows without clobbering an in-progress edit of the same node.
92
+ const lastCommitted = React.useRef(serialize(external));
93
+ React.useEffect(() => {
94
+ const next = serialize(external);
95
+ if (next !== lastCommitted.current) {
96
+ setRows(toRows(external, []));
97
+ lastCommitted.current = next;
98
+ }
99
+ }, [external]);
100
+ const flush = (nextRows) => {
101
+ const obj = rowsToObject(nextRows);
102
+ lastCommitted.current = serialize(obj);
103
+ onCommit(Object.keys(obj).length ? obj : undefined);
104
+ };
105
+ const setRowField = (id, patch) => {
106
+ setRows((rs) => rs.map((r) => (r.id === id ? { ...r, ...patch } : r)));
107
+ };
108
+ const addRow = () => {
109
+ setRows((rs) => [...rs, { id: uniqueId('kv', rs.map((r) => r.id)), key: '', raw: '' }]);
110
+ };
111
+ const removeRow = (id) => {
112
+ setRows((rs) => {
113
+ const next = rs.filter((r) => r.id !== id);
114
+ flush(next);
115
+ return next;
116
+ });
117
+ };
118
+ return (_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsxs("div", { className: "space-y-1.5", children: [rows.length === 0 && (_jsx("p", { className: "text-[11px] italic text-muted-foreground", children: emptyLabel })), rows.map((row) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Input, { value: row.key, onChange: (e) => setRowField(row.id, { key: e.target.value }), onBlur: () => flush(rows), onKeyDown: (e) => {
119
+ if (e.key === 'Enter')
120
+ e.target.blur();
121
+ }, placeholder: keyLabel, disabled: disabled, className: "h-8 flex-1 font-mono text-xs" }), _jsx(Input, { value: row.raw, onChange: (e) => setRowField(row.id, { raw: e.target.value }), onBlur: () => flush(rows), onKeyDown: (e) => {
122
+ if (e.key === 'Enter')
123
+ e.target.blur();
124
+ }, placeholder: valueLabel, disabled: disabled, className: "h-8 flex-1 text-xs" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-8 w-8 shrink-0 p-0 text-muted-foreground", onClick: () => removeRow(row.id), disabled: disabled, "aria-label": removeLabel, title: removeLabel, children: _jsx(X, { className: "h-3.5 w-3.5" }) })] }, row.id)))] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "h-7 w-full text-xs", onClick: addRow, disabled: disabled, children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), addLabel] }), help && _jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: help })] }));
125
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * FlowNodeConfigField — renders one scalar config control for a flow node,
3
+ * driven by a `FlowConfigField` descriptor. Bridges descriptor "kind" to the
4
+ * shared inspector field primitives and writes back to `node.config[key]`.
5
+ */
6
+ import * as React from 'react';
7
+ import type { FlowConfigField } from './flow-node-config';
8
+ import { type FlowReferenceContext } from './FlowReferenceField';
9
+ export interface FlowNodeConfigFieldProps {
10
+ field: FlowConfigField;
11
+ value: unknown;
12
+ onCommit: (value: unknown) => void;
13
+ disabled?: boolean;
14
+ locale?: string;
15
+ /** Draft + node context so `reference` fields can resolve their options. */
16
+ context?: FlowReferenceContext;
17
+ }
18
+ export declare function FlowNodeConfigField({ field, value, onCommit, disabled, locale, context }: FlowNodeConfigFieldProps): React.JSX.Element;