@object-ui/app-shell 6.2.3 → 7.0.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 (468) hide show
  1. package/CHANGELOG.md +948 -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 +170 -37
  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 +743 -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 +22 -0
  27. package/dist/console/ai/LiveCanvas.js +78 -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 +107 -4
  90. package/dist/hooks/useChatConversation.js +253 -25
  91. package/dist/hooks/useConsoleActionRuntime.d.ts +70 -0
  92. package/dist/hooks/useConsoleActionRuntime.js +560 -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 +16 -7
  110. package/dist/index.js +12 -4
  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 +32 -2
  124. package/dist/layout/ConsoleFloatingChatbot.js +374 -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 +218 -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/observability/index.d.ts +1 -0
  140. package/dist/observability/index.js +1 -0
  141. package/dist/observability/settleSignal.d.ts +64 -0
  142. package/dist/observability/settleSignal.js +131 -0
  143. package/dist/preview/DraftChangesPanel.d.ts +19 -0
  144. package/dist/preview/DraftChangesPanel.js +114 -0
  145. package/dist/preview/DraftPreviewBar.d.ts +8 -0
  146. package/dist/preview/DraftPreviewBar.js +86 -0
  147. package/dist/preview/PreviewDraftEmptyState.d.ts +16 -0
  148. package/dist/preview/PreviewDraftEmptyState.js +47 -0
  149. package/dist/preview/PreviewModeContext.d.ts +57 -0
  150. package/dist/preview/PreviewModeContext.js +99 -0
  151. package/dist/preview/UnpublishedAppBar.d.ts +8 -0
  152. package/dist/preview/UnpublishedAppBar.js +79 -0
  153. package/dist/preview/draftStatus.d.ts +20 -0
  154. package/dist/preview/draftStatus.js +27 -0
  155. package/dist/preview/usePublishAllDrafts.d.ts +18 -0
  156. package/dist/preview/usePublishAllDrafts.js +106 -0
  157. package/dist/providers/AdapterProvider.d.ts +1 -1
  158. package/dist/providers/AdapterProvider.js +6 -1
  159. package/dist/providers/ExpressionProvider.d.ts +1 -1
  160. package/dist/providers/MetadataProvider.d.ts +17 -2
  161. package/dist/providers/MetadataProvider.js +183 -12
  162. package/dist/runtime-config.d.ts +46 -2
  163. package/dist/runtime-config.js +39 -2
  164. package/dist/services/builtinComponents.js +68 -59
  165. package/dist/skeletons/SkeletonDashboard.d.ts +1 -1
  166. package/dist/skeletons/SkeletonDetail.d.ts +1 -1
  167. package/dist/skeletons/SkeletonGrid.d.ts +1 -1
  168. package/dist/utils/appRoute.d.ts +21 -0
  169. package/dist/utils/appRoute.js +25 -0
  170. package/dist/utils/deriveRelatedLists.d.ts +54 -0
  171. package/dist/utils/deriveRelatedLists.js +91 -0
  172. package/dist/utils/index.d.ts +4 -0
  173. package/dist/utils/index.js +3 -0
  174. package/dist/utils/managedByEmptyState.d.ts +8 -1
  175. package/dist/utils/managedByEmptyState.js +13 -7
  176. package/dist/utils/preferLocal.d.ts +18 -0
  177. package/dist/utils/preferLocal.js +24 -0
  178. package/dist/views/ActionConfirmDialog.d.ts +1 -1
  179. package/dist/views/ActionConfirmDialog.js +3 -1
  180. package/dist/views/ActionParamDialog.d.ts +6 -1
  181. package/dist/views/ActionParamDialog.js +9 -3
  182. package/dist/views/ActionResultDialog.d.ts +13 -0
  183. package/dist/views/ActionResultDialog.js +134 -0
  184. package/dist/views/ComponentNavView.d.ts +14 -1
  185. package/dist/views/CreateViewDialog.d.ts +1 -1
  186. package/dist/views/DashboardConfigPanel.d.ts +28 -0
  187. package/dist/views/DashboardConfigPanel.js +81 -0
  188. package/dist/views/DashboardView.d.ts +4 -3
  189. package/dist/views/DashboardView.js +38 -239
  190. package/dist/views/FlowRunner.d.ts +59 -0
  191. package/dist/views/FlowRunner.js +153 -0
  192. package/dist/views/InterfaceListPage.d.ts +49 -0
  193. package/dist/views/InterfaceListPage.js +347 -0
  194. package/dist/views/MetadataInspector.d.ts +2 -2
  195. package/dist/views/ObjectView.d.ts +1 -1
  196. package/dist/views/ObjectView.js +209 -532
  197. package/dist/views/PageView.d.ts +8 -3
  198. package/dist/views/PageView.js +45 -32
  199. package/dist/views/RecordDetailView.d.ts +1 -1
  200. package/dist/views/RecordDetailView.js +363 -148
  201. package/dist/views/RecordFormPage.d.ts +1 -1
  202. package/dist/views/RecordFormPage.js +26 -1
  203. package/dist/views/ReportConfigPanel.d.ts +37 -0
  204. package/dist/views/ReportConfigPanel.js +85 -0
  205. package/dist/views/ReportView.d.ts +1 -1
  206. package/dist/views/ReportView.js +116 -7
  207. package/dist/views/RuntimeDraftBar.d.ts +30 -0
  208. package/dist/views/RuntimeDraftBar.js +112 -0
  209. package/dist/views/SearchResultsPage.d.ts +1 -1
  210. package/dist/views/SearchResultsPage.js +8 -18
  211. package/dist/views/ViewConfigPanel.d.ts +24 -17
  212. package/dist/views/ViewConfigPanel.js +121 -77
  213. package/dist/views/index.d.ts +1 -1
  214. package/dist/views/index.js +1 -1
  215. package/dist/views/metadata-admin/AuditPanel.d.ts +28 -0
  216. package/dist/views/metadata-admin/AuditPanel.js +79 -0
  217. package/dist/views/metadata-admin/DiagnosticsPage.d.ts +20 -0
  218. package/dist/views/metadata-admin/DiagnosticsPage.js +69 -0
  219. package/dist/views/metadata-admin/DirectoryPage.d.ts +16 -1
  220. package/dist/views/metadata-admin/DirectoryPage.js +113 -24
  221. package/dist/views/metadata-admin/DraftReviewPanel.d.ts +33 -0
  222. package/dist/views/metadata-admin/DraftReviewPanel.js +77 -0
  223. package/dist/views/metadata-admin/EmbeddedItemEditor.d.ts +17 -1
  224. package/dist/views/metadata-admin/EmbeddedItemEditor.js +15 -8
  225. package/dist/views/metadata-admin/JsonSourceEditor.d.ts +37 -0
  226. package/dist/views/metadata-admin/JsonSourceEditor.js +178 -0
  227. package/dist/views/metadata-admin/LayeredDiff.d.ts +39 -1
  228. package/dist/views/metadata-admin/LayeredDiff.js +171 -5
  229. package/dist/views/metadata-admin/MetadataDetailDrawer.d.ts +15 -1
  230. package/dist/views/metadata-admin/MetadataTypeActions.d.ts +48 -0
  231. package/dist/views/metadata-admin/MetadataTypeActions.js +165 -0
  232. package/dist/views/metadata-admin/PackagesPage.d.ts +18 -0
  233. package/dist/views/metadata-admin/PackagesPage.js +395 -0
  234. package/dist/views/metadata-admin/PageShell.d.ts +1 -1
  235. package/dist/views/metadata-admin/PageShell.js +9 -4
  236. package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +35 -1
  237. package/dist/views/metadata-admin/QuickFind.d.ts +21 -1
  238. package/dist/views/metadata-admin/QuickFind.js +6 -3
  239. package/dist/views/metadata-admin/RelatedPanel.d.ts +24 -1
  240. package/dist/views/metadata-admin/RelatedPanel.js +20 -18
  241. package/dist/views/metadata-admin/ResourceEditPage.d.ts +40 -1
  242. package/dist/views/metadata-admin/ResourceEditPage.js +1223 -60
  243. package/dist/views/metadata-admin/ResourceHistoryPage.d.ts +39 -1
  244. package/dist/views/metadata-admin/ResourceHistoryPage.js +66 -16
  245. package/dist/views/metadata-admin/ResourceListPage.d.ts +13 -1
  246. package/dist/views/metadata-admin/ResourceListPage.js +266 -30
  247. package/dist/views/metadata-admin/ResourceRouter.d.ts +23 -1
  248. package/dist/views/metadata-admin/SchemaForm.d.ts +34 -1
  249. package/dist/views/metadata-admin/SchemaForm.js +559 -49
  250. package/dist/views/metadata-admin/StudioHomePage.d.ts +22 -0
  251. package/dist/views/metadata-admin/StudioHomePage.js +213 -0
  252. package/dist/views/metadata-admin/anchors.js +237 -24
  253. package/dist/views/metadata-admin/clientValidation.d.ts +50 -0
  254. package/dist/views/metadata-admin/clientValidation.js +169 -0
  255. package/dist/views/metadata-admin/color-variant-field.d.ts +30 -0
  256. package/dist/views/metadata-admin/color-variant-field.js +38 -0
  257. package/dist/views/metadata-admin/createDerive.d.ts +75 -0
  258. package/dist/views/metadata-admin/createDerive.js +179 -0
  259. package/dist/views/metadata-admin/dashboard-schema.d.ts +12 -0
  260. package/dist/views/metadata-admin/dashboard-schema.js +80 -0
  261. package/dist/views/metadata-admin/datasource/DatasourceResourcePage.d.ts +35 -0
  262. package/dist/views/metadata-admin/datasource/DatasourceResourcePage.js +327 -0
  263. package/dist/views/metadata-admin/datasource/register.d.ts +1 -0
  264. package/dist/views/metadata-admin/datasource/register.js +24 -0
  265. package/dist/views/metadata-admin/default-inspector-registry.d.ts +49 -0
  266. package/dist/views/metadata-admin/default-inspector-registry.js +8 -0
  267. package/dist/views/metadata-admin/default-schemas.js +115 -10
  268. package/dist/views/metadata-admin/external/ExternalDatasourcePanel.d.ts +27 -0
  269. package/dist/views/metadata-admin/external/ExternalDatasourcePanel.js +69 -0
  270. package/dist/views/metadata-admin/external/ImportObjectDialog.d.ts +27 -0
  271. package/dist/views/metadata-admin/external/ImportObjectDialog.js +77 -0
  272. package/dist/views/metadata-admin/external/SchemaBrowser.d.ts +16 -0
  273. package/dist/views/metadata-admin/external/SchemaBrowser.js +74 -0
  274. package/dist/views/metadata-admin/external/ValidationPanel.d.ts +16 -0
  275. package/dist/views/metadata-admin/external/ValidationPanel.js +68 -0
  276. package/dist/views/metadata-admin/external/api.d.ts +100 -0
  277. package/dist/views/metadata-admin/external/api.js +124 -0
  278. package/dist/views/metadata-admin/i18n.d.ts +1 -0
  279. package/dist/views/metadata-admin/i18n.js +1166 -2
  280. package/dist/views/metadata-admin/index.d.ts +8 -5
  281. package/dist/views/metadata-admin/index.js +12 -2
  282. package/dist/views/metadata-admin/inspector-registry.d.ts +51 -0
  283. package/dist/views/metadata-admin/inspector-registry.js +11 -0
  284. package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.d.ts +30 -0
  285. package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.js +180 -0
  286. package/dist/views/metadata-admin/inspectors/AppNavInspector.d.ts +16 -0
  287. package/dist/views/metadata-admin/inspectors/AppNavInspector.js +110 -0
  288. package/dist/views/metadata-admin/inspectors/ConditionBuilder.d.ts +29 -0
  289. package/dist/views/metadata-admin/inspectors/ConditionBuilder.js +154 -0
  290. package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.d.ts +28 -0
  291. package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.js +110 -0
  292. package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.d.ts +18 -0
  293. package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.js +139 -0
  294. package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.d.ts +21 -0
  295. package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.js +107 -0
  296. package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.d.ts +16 -0
  297. package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.js +45 -0
  298. package/dist/views/metadata-admin/inspectors/FlowInspector.d.ts +12 -0
  299. package/dist/views/metadata-admin/inspectors/FlowInspector.js +9 -0
  300. package/dist/views/metadata-admin/inspectors/FlowKeyValueField.d.ts +30 -0
  301. package/dist/views/metadata-admin/inspectors/FlowKeyValueField.js +125 -0
  302. package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.d.ts +18 -0
  303. package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.js +40 -0
  304. package/dist/views/metadata-admin/inspectors/FlowNodeInspector.d.ts +14 -0
  305. package/dist/views/metadata-admin/inspectors/FlowNodeInspector.js +140 -0
  306. package/dist/views/metadata-admin/inspectors/FlowObjectListField.d.ts +26 -0
  307. package/dist/views/metadata-admin/inspectors/FlowObjectListField.js +105 -0
  308. package/dist/views/metadata-admin/inspectors/FlowReferenceField.d.ts +83 -0
  309. package/dist/views/metadata-admin/inspectors/FlowReferenceField.js +181 -0
  310. package/dist/views/metadata-admin/inspectors/FlowStringListField.d.ts +21 -0
  311. package/dist/views/metadata-admin/inspectors/FlowStringListField.js +60 -0
  312. package/dist/views/metadata-admin/inspectors/InspectorComboField.d.ts +40 -0
  313. package/dist/views/metadata-admin/inspectors/InspectorComboField.js +61 -0
  314. package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.d.ts +21 -0
  315. package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.js +54 -0
  316. package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.d.ts +23 -0
  317. package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +330 -0
  318. package/dist/views/metadata-admin/inspectors/PageBlockInspector.d.ts +48 -0
  319. package/dist/views/metadata-admin/inspectors/PageBlockInspector.js +332 -0
  320. package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.d.ts +58 -0
  321. package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.js +160 -0
  322. package/dist/views/metadata-admin/inspectors/ViewColumnInspector.d.ts +19 -0
  323. package/dist/views/metadata-admin/inspectors/ViewColumnInspector.js +144 -0
  324. package/dist/views/metadata-admin/inspectors/ViewInspector.d.ts +19 -0
  325. package/dist/views/metadata-admin/inspectors/ViewInspector.js +21 -0
  326. package/dist/views/metadata-admin/inspectors/ViewVariantInspector.d.ts +54 -0
  327. package/dist/views/metadata-admin/inspectors/ViewVariantInspector.js +191 -0
  328. package/dist/views/metadata-admin/inspectors/_shared.d.ts +124 -0
  329. package/dist/views/metadata-admin/inspectors/_shared.js +113 -0
  330. package/dist/views/metadata-admin/inspectors/expression-validate.d.ts +26 -0
  331. package/dist/views/metadata-admin/inspectors/expression-validate.js +66 -0
  332. package/dist/views/metadata-admin/inspectors/flow-node-config.d.ts +143 -0
  333. package/dist/views/metadata-admin/inspectors/flow-node-config.js +461 -0
  334. package/dist/views/metadata-admin/inspectors/index.d.ts +1 -0
  335. package/dist/views/metadata-admin/inspectors/index.js +45 -0
  336. package/dist/views/metadata-admin/inspectors/json-schema-to-fields.d.ts +40 -0
  337. package/dist/views/metadata-admin/inspectors/json-schema-to-fields.js +227 -0
  338. package/dist/views/metadata-admin/inspectors/useDatasetFields.d.ts +72 -0
  339. package/dist/views/metadata-admin/inspectors/useDatasetFields.js +0 -0
  340. package/dist/views/metadata-admin/mergeServerFields.d.ts +65 -0
  341. package/dist/views/metadata-admin/mergeServerFields.js +56 -0
  342. package/dist/views/metadata-admin/preview-registry.d.ts +55 -0
  343. package/dist/views/metadata-admin/previews/ActionPreview.d.ts +25 -0
  344. package/dist/views/metadata-admin/previews/ActionPreview.js +238 -0
  345. package/dist/views/metadata-admin/previews/AddWidgetPicker.d.ts +12 -0
  346. package/dist/views/metadata-admin/previews/AddWidgetPicker.js +56 -0
  347. package/dist/views/metadata-admin/previews/AgentPreview.d.ts +24 -0
  348. package/dist/views/metadata-admin/previews/AgentPreview.js +100 -0
  349. package/dist/views/metadata-admin/previews/AppNavCanvas.d.ts +31 -0
  350. package/dist/views/metadata-admin/previews/AppNavCanvas.js +260 -0
  351. package/dist/views/metadata-admin/previews/AppPreview.d.ts +16 -1
  352. package/dist/views/metadata-admin/previews/AppPreview.js +23 -14
  353. package/dist/views/metadata-admin/previews/BookPreview.d.ts +20 -0
  354. package/dist/views/metadata-admin/previews/BookPreview.js +132 -0
  355. package/dist/views/metadata-admin/previews/DashboardPreview.d.ts +16 -1
  356. package/dist/views/metadata-admin/previews/DashboardPreview.js +110 -8
  357. package/dist/views/metadata-admin/previews/DatasetPreview.d.ts +18 -0
  358. package/dist/views/metadata-admin/previews/DatasetPreview.js +89 -0
  359. package/dist/views/metadata-admin/previews/DatasourcePreview.d.ts +23 -0
  360. package/dist/views/metadata-admin/previews/DatasourcePreview.js +68 -0
  361. package/dist/views/metadata-admin/previews/EmailTemplatePreview.d.ts +14 -1
  362. package/dist/views/metadata-admin/previews/FieldStub.d.ts +30 -0
  363. package/dist/views/metadata-admin/previews/FieldStub.js +104 -0
  364. package/dist/views/metadata-admin/previews/FieldsListEditor.d.ts +50 -0
  365. package/dist/views/metadata-admin/previews/FieldsListEditor.js +97 -0
  366. package/dist/views/metadata-admin/previews/FlowCanvas.d.ts +43 -0
  367. package/dist/views/metadata-admin/previews/FlowCanvas.js +328 -0
  368. package/dist/views/metadata-admin/previews/FlowPreview.d.ts +20 -0
  369. package/dist/views/metadata-admin/previews/FlowPreview.js +92 -0
  370. package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +46 -0
  371. package/dist/views/metadata-admin/previews/FlowRunsPanel.js +97 -0
  372. package/dist/views/metadata-admin/previews/FlowSimulatorPanel.d.ts +25 -0
  373. package/dist/views/metadata-admin/previews/FlowSimulatorPanel.js +170 -0
  374. package/dist/views/metadata-admin/previews/JobPreview.d.ts +28 -0
  375. package/dist/views/metadata-admin/previews/JobPreview.js +290 -0
  376. package/dist/views/metadata-admin/previews/ObjectFormCanvas.d.ts +30 -0
  377. package/dist/views/metadata-admin/previews/ObjectFormCanvas.js +547 -0
  378. package/dist/views/metadata-admin/previews/ObjectPreview.d.ts +14 -1
  379. package/dist/views/metadata-admin/previews/ObjectPreview.js +5 -30
  380. package/dist/views/metadata-admin/previews/OutlineStrip.d.ts +32 -0
  381. package/dist/views/metadata-admin/previews/OutlineStrip.js +8 -0
  382. package/dist/views/metadata-admin/previews/PageBlockCanvas.d.ts +49 -0
  383. package/dist/views/metadata-admin/previews/PageBlockCanvas.js +510 -0
  384. package/dist/views/metadata-admin/previews/PagePreview.d.ts +10 -1
  385. package/dist/views/metadata-admin/previews/PagePreview.js +90 -4
  386. package/dist/views/metadata-admin/previews/PermissionPreview.d.ts +27 -0
  387. package/dist/views/metadata-admin/previews/PermissionPreview.js +115 -0
  388. package/dist/views/metadata-admin/previews/PreviewShell.d.ts +29 -6
  389. package/dist/views/metadata-admin/previews/PreviewShell.js +16 -3
  390. package/dist/views/metadata-admin/previews/ReportPreview.d.ts +18 -1
  391. package/dist/views/metadata-admin/previews/ReportPreview.js +23 -15
  392. package/dist/views/metadata-admin/previews/RolePreview.d.ts +19 -0
  393. package/dist/views/metadata-admin/previews/RolePreview.js +14 -0
  394. package/dist/views/metadata-admin/previews/SkillPreview.d.ts +22 -0
  395. package/dist/views/metadata-admin/previews/SkillPreview.js +34 -0
  396. package/dist/views/metadata-admin/previews/ToolPreview.d.ts +25 -0
  397. package/dist/views/metadata-admin/previews/ToolPreview.js +122 -0
  398. package/dist/views/metadata-admin/previews/TranslationPreview.d.ts +25 -0
  399. package/dist/views/metadata-admin/previews/TranslationPreview.js +52 -0
  400. package/dist/views/metadata-admin/previews/ValidationPreview.d.ts +27 -0
  401. package/dist/views/metadata-admin/previews/ValidationPreview.js +110 -0
  402. package/dist/views/metadata-admin/previews/ViewColumnPanes.d.ts +62 -0
  403. package/dist/views/metadata-admin/previews/ViewColumnPanes.js +140 -0
  404. package/dist/views/metadata-admin/previews/ViewPreview.d.ts +23 -1
  405. package/dist/views/metadata-admin/previews/ViewPreview.js +101 -73
  406. package/dist/views/metadata-admin/previews/block-config.d.ts +82 -0
  407. package/dist/views/metadata-admin/previews/block-config.js +324 -0
  408. package/dist/views/metadata-admin/previews/block-types.d.ts +40 -0
  409. package/dist/views/metadata-admin/previews/block-types.js +110 -0
  410. package/dist/views/metadata-admin/previews/field-types.d.ts +53 -0
  411. package/dist/views/metadata-admin/previews/field-types.js +97 -0
  412. package/dist/views/metadata-admin/previews/flow-canvas-layout.d.ts +88 -0
  413. package/dist/views/metadata-admin/previews/flow-canvas-layout.js +190 -0
  414. package/dist/views/metadata-admin/previews/flow-canvas-parts.d.ts +88 -0
  415. package/dist/views/metadata-admin/previews/flow-canvas-parts.js +358 -0
  416. package/dist/views/metadata-admin/previews/form-preview.d.ts +24 -0
  417. package/dist/views/metadata-admin/previews/form-preview.js +29 -0
  418. package/dist/views/metadata-admin/previews/index.js +43 -0
  419. package/dist/views/metadata-admin/previews/object-fields-bridge.d.ts +66 -0
  420. package/dist/views/metadata-admin/previews/object-fields-bridge.js +171 -0
  421. package/dist/views/metadata-admin/previews/object-fields-io.d.ts +109 -0
  422. package/dist/views/metadata-admin/previews/object-fields-io.js +208 -0
  423. package/dist/views/metadata-admin/previews/simulator/flow-sim-types.d.ts +91 -0
  424. package/dist/views/metadata-admin/previews/simulator/flow-sim-types.js +2 -0
  425. package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.d.ts +8 -0
  426. package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.js +113 -0
  427. package/dist/views/metadata-admin/previews/simulator/flow-simulator.d.ts +44 -0
  428. package/dist/views/metadata-admin/previews/simulator/flow-simulator.js +316 -0
  429. package/dist/views/metadata-admin/previews/useDatasetCatalog.d.ts +47 -0
  430. package/dist/views/metadata-admin/previews/useDatasetCatalog.js +133 -0
  431. package/dist/views/metadata-admin/previews/useFlowNodePalette.d.ts +44 -0
  432. package/dist/views/metadata-admin/previews/useFlowNodePalette.js +124 -0
  433. package/dist/views/metadata-admin/previews/useMetaOptions.d.ts +8 -0
  434. package/dist/views/metadata-admin/previews/useMetaOptions.js +50 -0
  435. package/dist/views/metadata-admin/previews/useObjectFields.d.ts +23 -0
  436. package/dist/views/metadata-admin/previews/useObjectFields.js +79 -0
  437. package/dist/views/metadata-admin/previews/useObjectOptions.d.ts +8 -0
  438. package/dist/views/metadata-admin/previews/useObjectOptions.js +43 -0
  439. package/dist/views/metadata-admin/previews/view-column-io.d.ts +42 -0
  440. package/dist/views/metadata-admin/previews/view-column-io.js +73 -0
  441. package/dist/views/metadata-admin/previews/widget-types.d.ts +24 -0
  442. package/dist/views/metadata-admin/previews/widget-types.js +40 -0
  443. package/dist/views/metadata-admin/registry.d.ts +140 -19
  444. package/dist/views/metadata-admin/report-schema.d.ts +26 -0
  445. package/dist/views/metadata-admin/report-schema.js +121 -0
  446. package/dist/views/metadata-admin/useMetadata.d.ts +100 -2
  447. package/dist/views/metadata-admin/useMetadata.js +155 -4
  448. package/dist/views/metadata-admin/view-item-normalize.d.ts +20 -0
  449. package/dist/views/metadata-admin/view-item-normalize.js +68 -0
  450. package/dist/views/metadata-admin/view-schema.d.ts +16 -0
  451. package/dist/views/metadata-admin/view-schema.js +107 -0
  452. package/dist/views/metadata-admin/view-variant-model.d.ts +23 -0
  453. package/dist/views/metadata-admin/view-variant-model.js +64 -0
  454. package/dist/views/metadata-admin/widgets.d.ts +89 -1
  455. package/dist/views/metadata-admin/widgets.js +491 -17
  456. package/dist/views/runtime-metadata-persistence.d.ts +78 -0
  457. package/dist/views/runtime-metadata-persistence.js +89 -0
  458. package/dist/views/useOpenRecordList.d.ts +18 -0
  459. package/dist/views/useOpenRecordList.js +36 -0
  460. package/dist/views/userFilterUrlState.d.ts +15 -0
  461. package/dist/views/userFilterUrlState.js +53 -0
  462. package/dist/views/view-config-adapter.d.ts +38 -0
  463. package/dist/views/view-config-adapter.js +80 -0
  464. package/package.json +52 -34
  465. package/dist/views/DesignDrawer.d.ts +0 -28
  466. package/dist/views/DesignDrawer.js +0 -51
  467. package/dist/views/metadata-admin/DesignerEditorWrapper.d.ts +0 -68
  468. package/dist/views/metadata-admin/DesignerEditorWrapper.js +0 -158
@@ -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,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { t } from '../i18n';
3
+ import { InspectorShell, InspectorTextField, 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
+ onPatch({ edges: spliceArray(edges, index, next) });
31
+ };
32
+ const isDefault = edge.isDefault === true;
33
+ 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: () => {
34
+ onPatch({ edges: spliceArray(edges, index, null) });
35
+ onClearSelection();
36
+ }, 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 })] }), _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 }), (() => {
37
+ // ADR-0032 — flag a malformed edge guard (e.g. `{record.x}` brace-in-CEL)
38
+ // inline, with the same corrective message as build/agent validation.
39
+ const issue = isDefault ? null : validateExpressionClient('predicate', edge.condition);
40
+ return issue ? (_jsx("p", { className: "text-[11px] leading-snug text-destructive", role: "alert", children: issue.message })) : null;
41
+ })(), _jsx(InspectorCheckboxField, { label: t('engine.inspector.flowEdge.isDefault', locale), value: isDefault,
42
+ // The default ("else") branch is taken when no other guard matches, so
43
+ // it carries neither a condition nor a branch label — clear both.
44
+ 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) })] }));
45
+ }
@@ -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;
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { t } from '../i18n';
3
+ import { InspectorTextField, InspectorNumberField, InspectorSelectField, InspectorCheckboxField, } from './_shared';
4
+ import { Label } from '@object-ui/components';
5
+ import { FlowKeyValueField } from './FlowKeyValueField';
6
+ import { FlowStringListField } from './FlowStringListField';
7
+ import { FlowObjectListField } from './FlowObjectListField';
8
+ import { FlowReferenceField } from './FlowReferenceField';
9
+ import { validateExpressionClient } from './expression-validate';
10
+ export function FlowNodeConfigField({ field, value, onCommit, disabled, locale, context }) {
11
+ const control = (() => {
12
+ switch (field.kind) {
13
+ case 'reference':
14
+ return (_jsx(FlowReferenceField, { field: field, value: value, onCommit: (v) => onCommit(v), disabled: disabled, context: context }));
15
+ case 'keyValue':
16
+ return (_jsx(FlowKeyValueField, { label: field.label, value: value, onCommit: (v) => onCommit(v), disabled: disabled, addLabel: t('engine.inspector.flowNode.kv.add', locale), keyLabel: t('engine.inspector.flowNode.kv.key', locale), valueLabel: t('engine.inspector.flowNode.kv.value', locale), removeLabel: t('engine.inspector.flowNode.kv.remove', locale), emptyLabel: t('engine.inspector.flowNode.kv.empty', locale) }));
17
+ case 'stringList':
18
+ return (_jsx(FlowStringListField, { label: field.label, value: value, onCommit: (v) => onCommit(v), disabled: disabled, addLabel: t('engine.inspector.flowNode.list.add', locale), itemLabel: t('engine.inspector.flowNode.list.item', locale), removeLabel: t('engine.inspector.flowNode.list.remove', locale), emptyLabel: t('engine.inspector.flowNode.list.empty', locale) }));
19
+ case 'objectList':
20
+ return (_jsx(FlowObjectListField, { label: field.label, columns: field.columns ?? [], value: value, onCommit: (v) => onCommit(v), disabled: disabled, addLabel: t('engine.inspector.flowNode.list.add', locale), removeLabel: t('engine.inspector.flowNode.list.remove', locale), emptyLabel: t('engine.inspector.flowNode.list.empty', locale), context: context }));
21
+ case 'number':
22
+ return (_jsx(InspectorNumberField, { label: field.label, value: typeof value === 'number' ? value : value != null && value !== '' ? Number(value) : undefined, placeholder: field.placeholder, onCommit: (v) => onCommit(v), disabled: disabled }));
23
+ case 'boolean':
24
+ return (_jsx(InspectorCheckboxField, { label: field.label, value: value === true, onCommit: (v) => onCommit(v), disabled: disabled }));
25
+ case 'select':
26
+ return (_jsx(InspectorSelectField, { label: field.label, value: value != null ? String(value) : '', options: field.options ?? [], onCommit: (v) => onCommit(v), disabled: disabled }));
27
+ case 'textarea':
28
+ return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: field.label }), _jsx("textarea", { value: value != null ? String(value) : '', onChange: (e) => onCommit(e.target.value), placeholder: field.placeholder, disabled: disabled, rows: 4, className: "w-full rounded border bg-background px-2 py-1.5 font-mono text-xs" })] }));
29
+ case 'expression':
30
+ case 'text':
31
+ default:
32
+ return (_jsx(InspectorTextField, { label: field.label, value: value != null ? String(value) : '', placeholder: field.placeholder, onCommit: (v) => onCommit(v), disabled: disabled, mono: field.kind === 'expression' }));
33
+ }
34
+ })();
35
+ // ADR-0032 — surface a malformed condition (e.g. the `{record.x}` brace-in-CEL
36
+ // mistake) inline, as the author types, with the same corrective message the
37
+ // build and the agent tool emit. Only checked for expression-bearing fields.
38
+ const exprIssue = field.kind === 'expression' ? validateExpressionClient('predicate', value) : null;
39
+ return (_jsxs("div", { className: "space-y-1", children: [control, exprIssue && (_jsx("p", { className: "text-[11px] leading-snug text-destructive", role: "alert", children: exprIssue.message })), field.help && !exprIssue && (_jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: field.help }))] }));
40
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * FlowNodeInspector — scoped editor for the selected flow node.
3
+ *
4
+ * Selection shape: { kind: 'node', id: <nodeId> }
5
+ * Patches: draft.nodes[i] = {...node, ...updates}
6
+ *
7
+ * Beyond id / label / type / description, each node type exposes a set of
8
+ * typed form fields (see `flow-node-config`) that edit scalar keys on
9
+ * `node.config`. Any remaining config keys (objects, arrays, bespoke flags)
10
+ * are surfaced in an "Advanced (JSON)" block so authors are never locked out.
11
+ */
12
+ import * as React from 'react';
13
+ import type { MetadataInspectorProps } from '../inspector-registry';
14
+ export declare function FlowNodeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }: MetadataInspectorProps): React.JSX.Element;
@@ -0,0 +1,140 @@
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
+ * FlowNodeInspector — scoped editor for the selected flow node.
5
+ *
6
+ * Selection shape: { kind: 'node', id: <nodeId> }
7
+ * Patches: draft.nodes[i] = {...node, ...updates}
8
+ *
9
+ * Beyond id / label / type / description, each node type exposes a set of
10
+ * typed form fields (see `flow-node-config`) that edit scalar keys on
11
+ * `node.config`. Any remaining config keys (objects, arrays, bespoke flags)
12
+ * are surfaced in an "Advanced (JSON)" block so authors are never locked out.
13
+ */
14
+ import * as React from 'react';
15
+ import { Plus } from 'lucide-react';
16
+ import { t } from '../i18n';
17
+ import { InspectorShell, InspectorTextField, InspectorSelectField, InspectorRemoveButton, InspectorEmptyState, spliceArray, } from './_shared';
18
+ import { fieldsForNodeType, isFieldVisible, getFieldValue, configKeyOf, FLOW_NODE_TYPE_OPTIONS, } from './flow-node-config';
19
+ import { jsonSchemaToFlowFields } from './json-schema-to-fields';
20
+ import { useActionConfigSchemas } from '../previews/useFlowNodePalette';
21
+ import { FlowNodeConfigField } from './FlowNodeConfigField';
22
+ function asConfig(node) {
23
+ const c = node?.config;
24
+ return c && typeof c === 'object' && !Array.isArray(c) ? c : {};
25
+ }
26
+ /**
27
+ * Immutably set `value` at `path` on a plain object, pruning any intermediate
28
+ * object that becomes empty (so e.g. clearing the last `waitEventConfig` key
29
+ * removes the whole block). Empty string / null / undefined deletes the leaf.
30
+ */
31
+ function setAtPath(obj, path, value) {
32
+ const [head, ...rest] = path;
33
+ const next = { ...obj };
34
+ if (rest.length === 0) {
35
+ if (value === undefined || value === null || value === '')
36
+ delete next[head];
37
+ else
38
+ next[head] = value;
39
+ }
40
+ else {
41
+ const cur = next[head];
42
+ const base = cur && typeof cur === 'object' && !Array.isArray(cur) ? cur : {};
43
+ const child = setAtPath(base, rest, value);
44
+ if (Object.keys(child).length === 0)
45
+ delete next[head];
46
+ else
47
+ next[head] = child;
48
+ }
49
+ return next;
50
+ }
51
+ export function FlowNodeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }) {
52
+ const nodes = Array.isArray(draft.nodes) ? draft.nodes : [];
53
+ const index = nodes.findIndex((n) => n?.id === selection.id);
54
+ const node = index >= 0 ? nodes[index] : null;
55
+ // Server-driven property form: when the running engine publishes a config
56
+ // JSON Schema for this node type (ADR-0018 §configSchema — e.g. the ADR-0019
57
+ // approval node), derive the form from it so the designer stays in lock-step
58
+ // with the backend. Falls back to the hardcoded field group when no schema is
59
+ // published (offline / plugin absent / older backend).
60
+ const configSchemas = useActionConfigSchemas();
61
+ const fields = React.useMemo(() => {
62
+ const schema = node?.type ? configSchemas[node.type] : undefined;
63
+ const serverFields = schema !== undefined ? jsonSchemaToFlowFields(schema) : null;
64
+ return serverFields ?? fieldsForNodeType(node?.type);
65
+ }, [configSchemas, node?.type]);
66
+ const config = asConfig(node);
67
+ const visibleFields = fields.filter((f) => isFieldVisible(f, node, fields));
68
+ // Only fields stored under `config` "own" a config key; spec-structured
69
+ // blocks (waitEventConfig, etc.) and top-level timeoutMs never suppress an
70
+ // Advanced key.
71
+ const ownedConfigKeys = React.useMemo(() => {
72
+ const s = new Set();
73
+ for (const f of fields) {
74
+ const k = configKeyOf(f);
75
+ if (k)
76
+ s.add(k);
77
+ }
78
+ return s;
79
+ }, [fields]);
80
+ const extraJson = React.useMemo(() => {
81
+ const extra = Object.fromEntries(Object.entries(config).filter(([k]) => !ownedConfigKeys.has(k)));
82
+ return Object.keys(extra).length ? JSON.stringify(extra, null, 2) : '';
83
+ // Recompute when the node identity changes (patch) or the known keys change.
84
+ }, [node, ownedConfigKeys]); // eslint-disable-line react-hooks/exhaustive-deps
85
+ const [advText, setAdvText] = React.useState(extraJson);
86
+ const [advError, setAdvError] = React.useState(null);
87
+ const [advOpen, setAdvOpen] = React.useState(extraJson.trim() !== '');
88
+ // Reveals the optional custom-keys editor on nodes that currently have none.
89
+ const [advReveal, setAdvReveal] = React.useState(false);
90
+ React.useEffect(() => {
91
+ setAdvText(extraJson);
92
+ setAdvError(null);
93
+ setAdvOpen(extraJson.trim() !== '');
94
+ setAdvReveal(false);
95
+ }, [extraJson]);
96
+ if (!node) {
97
+ return (_jsx(InspectorShell, { kindLabel: t('engine.inspector.flowNode.kind', locale), title: selection.label ?? selection.id, onClose: onClearSelection, closeLabel: t('engine.inspector.flowNode.close', locale), children: _jsx(InspectorEmptyState, { message: selection.id }) }));
98
+ }
99
+ const patchNode = (updates) => {
100
+ onPatch({ nodes: spliceArray(nodes, index, { ...node, ...updates }) });
101
+ };
102
+ const hasExtras = extraJson.trim() !== '';
103
+ const setField = (path, value) => {
104
+ const nextNode = setAtPath(node, path, value);
105
+ onPatch({ nodes: spliceArray(nodes, index, nextNode) });
106
+ };
107
+ const commitAdvanced = () => {
108
+ try {
109
+ const parsed = advText.trim() === '' ? {} : JSON.parse(advText);
110
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
111
+ throw new Error('Must be a JSON object');
112
+ // Form-owned config keys always win: the Advanced block may only set keys
113
+ // that no form field owns, so it can never overwrite or resurrect one.
114
+ const knownPart = Object.fromEntries(Object.entries(config).filter(([k]) => ownedConfigKeys.has(k)));
115
+ const extrasPart = Object.fromEntries(Object.entries(parsed).filter(([k]) => !ownedConfigKeys.has(k)));
116
+ const merged = { ...knownPart, ...extrasPart };
117
+ setAdvError(null);
118
+ const nextNode = { ...node };
119
+ if (Object.keys(merged).length === 0)
120
+ delete nextNode.config;
121
+ else
122
+ nextNode.config = merged;
123
+ onPatch({ nodes: spliceArray(nodes, index, nextNode) });
124
+ }
125
+ catch (e) {
126
+ setAdvError(String(e.message));
127
+ }
128
+ };
129
+ const remove = () => {
130
+ onPatch({ nodes: spliceArray(nodes, index, null) });
131
+ onClearSelection();
132
+ };
133
+ const typeOptions = FLOW_NODE_TYPE_OPTIONS.includes(node.type)
134
+ ? [...FLOW_NODE_TYPE_OPTIONS]
135
+ : [...FLOW_NODE_TYPE_OPTIONS, node.type ?? ''].filter(Boolean);
136
+ return (_jsxs(InspectorShell, { kindLabel: t('engine.inspector.flowNode.kind', locale), title: node.label || node.id, onClose: onClearSelection, closeLabel: t('engine.inspector.flowNode.close', locale), footer: _jsx(InspectorRemoveButton, { label: t('engine.inspector.flowNode.remove', locale), onClick: remove, disabled: readOnly }), children: [_jsx(InspectorTextField, { label: t('engine.inspector.flowNode.id', locale), value: node.id, onCommit: (v) => patchNode({ id: v }), disabled: readOnly, mono: true }), _jsx(InspectorTextField, { label: t('engine.inspector.flowNode.label', locale), value: node.label ?? '', onCommit: (v) => patchNode({ label: v }), disabled: readOnly }), _jsx(InspectorSelectField, { label: t('engine.inspector.flowNode.type', locale), value: node.type, options: typeOptions.map((v) => ({ value: v, label: v })), onCommit: (v) => patchNode({ type: v }), disabled: readOnly }), _jsx(InspectorTextField, { label: t('engine.inspector.flowNode.description', locale), value: node.description ?? '', onCommit: (v) => patchNode({ description: v || undefined }), disabled: readOnly }), fields.length === 0 ? (_jsx("p", { className: "pt-1 text-xs italic text-muted-foreground", children: t('engine.inspector.flowNode.noConfig', locale) })) : (visibleFields.length > 0 && (_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.flowNode.configuration', locale) }), _jsx("span", { className: "h-px flex-1 bg-border", "aria-hidden": true })] }))), visibleFields.map((field) => (_jsx(FlowNodeConfigField, { field: field, value: getFieldValue(node, field), onCommit: (v) => setField(field.path, v), disabled: readOnly, locale: locale, context: { draft, node } }, field.id))), hasExtras || advReveal ? (_jsxs("details", { className: "group rounded border bg-muted/20", open: advOpen, onToggle: (e) => setAdvOpen(e.target.open), children: [_jsx("summary", { className: "cursor-pointer select-none px-2 py-1.5 text-xs font-medium text-muted-foreground", children: t('engine.inspector.flowNode.advanced', locale) }), _jsxs("div", { className: "space-y-1 border-t p-2", children: [_jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: t('engine.inspector.flowNode.advancedHint', locale) }), _jsx("textarea", { value: advText, onChange: (e) => setAdvText(e.target.value), onBlur: commitAdvanced, disabled: readOnly, rows: 6, placeholder: "{ }", className: "w-full rounded border bg-background px-2 py-1.5 font-mono text-xs" }), advError && _jsx("div", { className: "text-xs text-destructive", children: advError })] })] })) : (!readOnly && (_jsxs("button", { type: "button", onClick: () => {
137
+ setAdvReveal(true);
138
+ setAdvOpen(true);
139
+ }, className: "inline-flex items-center gap-1 self-start text-[11px] text-muted-foreground transition-colors hover:text-foreground", children: [_jsx(Plus, { className: "h-3 w-3" }), t('engine.inspector.flowNode.advanced', locale)] })))] }));
140
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * FlowObjectListField — a repeatable array-of-objects editor driven by a column
3
+ * schema (e.g. a screen node's `fields`: a list of `{name,label,type,required,
4
+ * visibleWhen}` definitions).
5
+ *
6
+ * Like the sibling key/value and string-list editors, rows are held in LOCAL
7
+ * state with a STABLE id and flushed on blur / Enter / add / remove so a row
8
+ * never remounts mid-keystroke. Empty per-cell values are pruned; a row with no
9
+ * populated cells is dropped on flush; an empty list commits `undefined`.
10
+ */
11
+ import * as React from 'react';
12
+ import type { FlowConfigColumn } from './flow-node-config';
13
+ import { type FlowReferenceContext } from './FlowReferenceField';
14
+ export interface FlowObjectListFieldProps {
15
+ label: string;
16
+ columns: FlowConfigColumn[];
17
+ value: unknown;
18
+ onCommit: (value: Array<Record<string, unknown>> | undefined) => void;
19
+ disabled?: boolean;
20
+ addLabel: string;
21
+ removeLabel: string;
22
+ emptyLabel: string;
23
+ /** Draft + node context so `reference` columns can resolve their options. */
24
+ context?: FlowReferenceContext;
25
+ }
26
+ export declare function FlowObjectListField({ label, columns, value, onCommit, disabled, addLabel, removeLabel, emptyLabel, context, }: FlowObjectListFieldProps): React.JSX.Element;
@@ -0,0 +1,105 @@
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
+ * FlowObjectListField — a repeatable array-of-objects editor driven by a column
5
+ * schema (e.g. a screen node's `fields`: a list of `{name,label,type,required,
6
+ * visibleWhen}` definitions).
7
+ *
8
+ * Like the sibling key/value and string-list editors, rows are held in LOCAL
9
+ * state with a STABLE id and flushed on blur / Enter / add / remove so a row
10
+ * never remounts mid-keystroke. Empty per-cell values are pruned; a row with no
11
+ * populated cells is dropped on flush; an empty list commits `undefined`.
12
+ */
13
+ import * as React from 'react';
14
+ import { Plus, X } from 'lucide-react';
15
+ import { Button, Input, Label, Checkbox } from '@object-ui/components';
16
+ import { uniqueId } from './_shared';
17
+ import { ReferenceCombobox, resolveRefKind } from './FlowReferenceField';
18
+ function toRows(list, columns) {
19
+ const ids = [];
20
+ return list.map((item) => {
21
+ const id = uniqueId('ol', ids);
22
+ ids.push(id);
23
+ const values = {};
24
+ for (const col of columns) {
25
+ const v = item[col.key];
26
+ if (col.kind === 'boolean')
27
+ values[col.key] = v === true;
28
+ else if (v != null)
29
+ values[col.key] = String(v);
30
+ else
31
+ values[col.key] = '';
32
+ }
33
+ return { id, values };
34
+ });
35
+ }
36
+ function rowsToList(rows, columns) {
37
+ const out = [];
38
+ for (const row of rows) {
39
+ const obj = {};
40
+ let hasValue = false;
41
+ for (const col of columns) {
42
+ const v = row.values[col.key];
43
+ if (col.kind === 'boolean') {
44
+ if (v === true) {
45
+ obj[col.key] = true;
46
+ hasValue = true;
47
+ }
48
+ }
49
+ else if (typeof v === 'string' && v.trim() !== '') {
50
+ obj[col.key] = v.trim();
51
+ hasValue = true;
52
+ }
53
+ }
54
+ if (hasValue)
55
+ out.push(obj);
56
+ }
57
+ return out;
58
+ }
59
+ export function FlowObjectListField({ label, columns, value, onCommit, disabled, addLabel, removeLabel, emptyLabel, context, }) {
60
+ const external = React.useMemo(() => Array.isArray(value)
61
+ ? value.filter((v) => v && typeof v === 'object')
62
+ : [], [value]);
63
+ const [rows, setRows] = React.useState(() => toRows(external, columns));
64
+ const lastCommitted = React.useRef(JSON.stringify(external));
65
+ React.useEffect(() => {
66
+ const next = JSON.stringify(external);
67
+ if (next !== lastCommitted.current) {
68
+ setRows(toRows(external, columns));
69
+ lastCommitted.current = next;
70
+ }
71
+ }, [external, columns]);
72
+ const flush = (nextRows) => {
73
+ const list = rowsToList(nextRows, columns);
74
+ lastCommitted.current = JSON.stringify(list);
75
+ onCommit(list.length ? list : undefined);
76
+ };
77
+ const setCell = (id, key, v) => {
78
+ setRows((rs) => rs.map((r) => (r.id === id ? { ...r, values: { ...r.values, [key]: v } } : r)));
79
+ };
80
+ const addRow = () => {
81
+ const values = {};
82
+ for (const col of columns)
83
+ values[col.key] = col.kind === 'boolean' ? false : '';
84
+ setRows((rs) => [...rs, { id: uniqueId('ol', rs.map((r) => r.id)), values }]);
85
+ };
86
+ const removeRow = (id) => {
87
+ setRows((rs) => {
88
+ const next = rs.filter((r) => r.id !== id);
89
+ flush(next);
90
+ return next;
91
+ });
92
+ };
93
+ return (_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsxs("div", { className: "space-y-2", children: [rows.length === 0 && (_jsx("p", { className: "text-[11px] italic text-muted-foreground", children: emptyLabel })), rows.map((row) => (_jsxs("div", { className: "rounded border bg-muted/30 p-2", children: [_jsx("div", { className: "mb-1 flex justify-end", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-6 w-6 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" }) }) }), _jsx("div", { className: "space-y-1.5", children: columns.map((col) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "w-24 shrink-0 text-[11px] text-muted-foreground", children: col.label }), col.kind === 'boolean' ? (_jsx(Checkbox, { checked: row.values[col.key] === true, onCheckedChange: (c) => {
94
+ setRows((rs) => {
95
+ const next = rs.map((r) => r.id === row.id
96
+ ? { ...r, values: { ...r.values, [col.key]: c === true } }
97
+ : r);
98
+ flush(next);
99
+ return next;
100
+ });
101
+ }, disabled: disabled })) : col.kind === 'reference' ? (_jsx("div", { className: "flex-1", children: _jsx(ReferenceCombobox, { resolved: resolveRefKind(col.ref, (k) => row.values[k]), value: typeof row.values[col.key] === 'string' ? row.values[col.key] : '', onCommit: (v) => setCell(row.id, col.key, typeof v === 'string' ? v : ''), onBlur: () => flush(rows), placeholder: col.placeholder, disabled: disabled, context: context, showHint: false }) })) : (_jsx(Input, { value: typeof row.values[col.key] === 'string' ? row.values[col.key] : '', onChange: (e) => setCell(row.id, col.key, e.target.value), onBlur: () => flush(rows), onKeyDown: (e) => {
102
+ if (e.key === 'Enter')
103
+ e.target.blur();
104
+ }, placeholder: col.placeholder, disabled: disabled, className: `h-8 flex-1 text-xs${col.kind === 'expression' ? ' font-mono' : ''}` }))] }, col.key))) })] }, 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] })] }));
105
+ }