@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,32 @@
1
+ /**
2
+ * OutlineStrip — clickable chip strip that lets users select
3
+ * sub-elements inside a preview whose main canvas renders through a
4
+ * sealed external renderer (SchemaRenderer, ReportRenderer, …) and
5
+ * therefore can't intercept clicks directly.
6
+ *
7
+ * The strip sits above the canvas. Each chip emits a selection on
8
+ * click; the currently-selected one gets a ring. Empty list collapses
9
+ * the strip entirely so the canvas takes the full preview height
10
+ * outside design mode.
11
+ */
12
+ import * as React from 'react';
13
+ export interface OutlineEntry {
14
+ /** Selection id to emit. */
15
+ id: string;
16
+ /** Human-readable chip label. */
17
+ label: string;
18
+ }
19
+ export declare function OutlineStrip({ title, entries, selectedId, onSelect, onAdd, addLabel, }: {
20
+ title: string;
21
+ entries: OutlineEntry[];
22
+ selectedId: string | null;
23
+ onSelect: (entry: OutlineEntry) => void;
24
+ /**
25
+ * Optional: render a `+` chip at the end. Clicking it should append
26
+ * a new item to the underlying array, set selection to the new item,
27
+ * and let the inspector open immediately.
28
+ */
29
+ onAdd?: () => void;
30
+ /** Tooltip / aria-label for the Add chip. Defaults to "Add". */
31
+ addLabel?: string;
32
+ }): React.JSX.Element | null;
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Plus } from 'lucide-react';
3
+ import { cn } from '@object-ui/components';
4
+ export function OutlineStrip({ title, entries, selectedId, onSelect, onAdd, addLabel, }) {
5
+ if (entries.length === 0 && !onAdd)
6
+ return null;
7
+ return (_jsxs("div", { className: "border-b bg-muted/30 px-3 py-2", children: [_jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground mb-1.5", children: title }), _jsxs("div", { className: "flex flex-wrap gap-1.5", children: [entries.map((e) => (_jsx("button", { type: "button", onClick: (ev) => { ev.stopPropagation(); onSelect(e); }, className: cn('rounded border bg-background px-2 py-0.5 text-xs hover:border-primary/50 cursor-pointer', selectedId === e.id && 'ring-2 ring-primary border-primary'), children: e.label }, e.id))), onAdd && (_jsxs("button", { type: "button", onClick: (ev) => { ev.stopPropagation(); onAdd(); }, className: "rounded border border-dashed bg-background px-2 py-0.5 text-xs text-muted-foreground hover:border-primary hover:text-primary cursor-pointer inline-flex items-center gap-1", "aria-label": addLabel ?? 'Add', title: addLabel ?? 'Add', children: [_jsx(Plus, { className: "h-3 w-3" }), _jsx("span", { children: addLabel ?? 'Add' })] }))] })] }));
8
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * PageBlockCanvas — form-designer-style preview for a Page metadata
3
+ * draft. Mirrors {@link ObjectFormCanvas}'s pattern: each block becomes
4
+ * a clickable card with a type badge, drag handle, and inline-rename
5
+ * affordance on its label. Regions become group sections that accept
6
+ * drops to reassign blocks.
7
+ *
8
+ * Supports only the canonical Page shape (`regions[].components[]`).
9
+ * Pages using the raw `children[]` shape fall back to the existing
10
+ * SchemaRenderer preview (no inline editing).
11
+ *
12
+ * Selection emits `{ kind: 'block', id: 'regions[i].components[j]' }`
13
+ * matching PageBlockInspector.
14
+ */
15
+ import * as React from 'react';
16
+ import type { MetadataSelection } from '../preview-registry';
17
+ /** Build the schema handed to SchemaRenderer, neutralising overlay form types so
18
+ * a live form block never mounts a modal over the design canvas. SchemaRenderer
19
+ * needs a `type` discriminator; the block always carries one. */
20
+ export declare function toCanvasSchema(block: Block): Record<string, unknown>;
21
+ interface Block {
22
+ type?: string;
23
+ id?: string;
24
+ label?: string;
25
+ title?: string;
26
+ children?: Block[];
27
+ [k: string]: unknown;
28
+ }
29
+ interface Region {
30
+ name?: string;
31
+ width?: string;
32
+ components?: Block[];
33
+ }
34
+ export interface PageBlockCanvasProps {
35
+ draft: Record<string, unknown>;
36
+ onPatch?: (patch: Record<string, unknown>) => void;
37
+ selection?: MetadataSelection | null;
38
+ onSelectionChange?: (next: MetadataSelection | null) => void;
39
+ }
40
+ /** Canonical record-page slots, in render order. A `kind:'slotted'` page
41
+ * overrides individual slots; unoverridden ones are filled by the synthesizer.
42
+ * We surface all of them so an author can override an inherited slot too. */
43
+ export declare const SLOT_ORDER: readonly ["header", "actions", "alerts", "highlights", "details", "tabs", "discussion"];
44
+ /** slots object → one region per slot (single component normalised to array). */
45
+ export declare function slotsToRegions(slots: Record<string, unknown> | undefined): Region[];
46
+ /** regions (one per slot) → slots object; empty slots are omitted (= inherited). */
47
+ export declare function regionsToSlots(regions: Region[]): Record<string, unknown>;
48
+ export declare function PageBlockCanvas({ draft, onPatch, selection, onSelectionChange, }: PageBlockCanvasProps): React.JSX.Element;
49
+ export {};
@@ -0,0 +1,510 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
3
+ /**
4
+ * PageBlockCanvas — form-designer-style preview for a Page metadata
5
+ * draft. Mirrors {@link ObjectFormCanvas}'s pattern: each block becomes
6
+ * a clickable card with a type badge, drag handle, and inline-rename
7
+ * affordance on its label. Regions become group sections that accept
8
+ * drops to reassign blocks.
9
+ *
10
+ * Supports only the canonical Page shape (`regions[].components[]`).
11
+ * Pages using the raw `children[]` shape fall back to the existing
12
+ * SchemaRenderer preview (no inline editing).
13
+ *
14
+ * Selection emits `{ kind: 'block', id: 'regions[i].components[j]' }`
15
+ * matching PageBlockInspector.
16
+ */
17
+ import * as React from 'react';
18
+ import { Badge, Button, cn, Popover, PopoverContent, PopoverTrigger, } from '@object-ui/components';
19
+ import { GripVertical, Plus } from 'lucide-react';
20
+ import { BLOCK_TYPE_META, TYPES_BY_CATEGORY, CATEGORY_LABEL_EN, UnknownBlockIcon, resolveBlockTone, } from './block-types';
21
+ import { parsePath, hopsToPath, getByPath, setByPath } from '../inspectors/PageBlockInspector';
22
+ import { SchemaRenderer, PreviewModeProvider } from '@object-ui/react';
23
+ import { PreviewErrorBoundary } from './PreviewShell';
24
+ import { isOverlayFormType } from './form-preview';
25
+ /** Build the schema handed to SchemaRenderer, neutralising overlay form types so
26
+ * a live form block never mounts a modal over the design canvas. SchemaRenderer
27
+ * needs a `type` discriminator; the block always carries one. */
28
+ export function toCanvasSchema(block) {
29
+ const schema = {
30
+ ...block,
31
+ type: String(block?.type ?? ''),
32
+ };
33
+ // formType lives under `properties` (canonical) but may also be hoisted to the
34
+ // top level; neutralise whichever carries an overlay type.
35
+ const props = schema.properties && typeof schema.properties === 'object'
36
+ ? schema.properties
37
+ : undefined;
38
+ const formType = (props?.formType ?? schema.formType);
39
+ if (isOverlayFormType(formType)) {
40
+ if (props)
41
+ schema.properties = { ...props, formType: 'simple' };
42
+ if ('formType' in schema)
43
+ schema.formType = 'simple';
44
+ }
45
+ return schema;
46
+ }
47
+ /** Defer mounting until an element scrolls near the viewport. Renders immediately
48
+ * in non-browser / test environments (no real IntersectionObserver, or under
49
+ * vitest) so server rendering and tests are unaffected; lazy only in the browser.
50
+ * Once in view it stays mounted — re-mounting a data block would re-fetch. */
51
+ function useLazyInView(rootMargin = '300px') {
52
+ const ref = React.useRef(null);
53
+ const [inView, setInView] = React.useState(() => {
54
+ if (typeof IntersectionObserver === 'undefined')
55
+ return true;
56
+ try {
57
+ if (import.meta.env?.MODE === 'test')
58
+ return true;
59
+ }
60
+ catch {
61
+ /* import.meta unavailable — fall through to lazy */
62
+ }
63
+ return false;
64
+ });
65
+ React.useEffect(() => {
66
+ if (inView)
67
+ return;
68
+ const el = ref.current;
69
+ if (!el)
70
+ return;
71
+ const io = new IntersectionObserver((entries) => {
72
+ if (entries.some((e) => e.isIntersecting)) {
73
+ setInView(true);
74
+ io.disconnect();
75
+ }
76
+ }, { rootMargin });
77
+ io.observe(el);
78
+ return () => io.disconnect();
79
+ }, [inView, rootMargin]);
80
+ return { ref, inView };
81
+ }
82
+ /** Render a single block via the real runtime renderer, behind a click-trap, so
83
+ * the design canvas mirrors the live preview. Mounting is deferred until the
84
+ * block scrolls near the viewport: data-bound blocks (grids, related lists,
85
+ * repeaters) each fetch on mount, so a tall page would otherwise fire every
86
+ * query at once. Capped height keeps a tall widget from dominating the canvas. */
87
+ function BlockLivePreview({ block, maxHeightClass = 'max-h-72' }) {
88
+ const typeStr = String(block?.type ?? '');
89
+ const { ref, inView } = useLazyInView();
90
+ return (_jsx("div", { ref: ref, className: cn('pointer-events-none select-none overflow-hidden p-3', maxHeightClass), children: inView ? (_jsx(PreviewErrorBoundary, { fallbackHint: `"${typeStr}" can't render with its current configuration — check its Properties.`, children: _jsx(PreviewModeProvider, { children: _jsx(SchemaRenderer, { schema: toCanvasSchema(block) }) }) })) : (_jsx("div", { className: "min-h-[64px] animate-pulse rounded bg-muted/40", "aria-hidden": "true" })) }));
91
+ }
92
+ /** Tailwind needs static class names — map a column count to a grid class. */
93
+ const GRID_COLS_CLASS = {
94
+ 1: 'grid-cols-1', 2: 'grid-cols-2', 3: 'grid-cols-3',
95
+ 4: 'grid-cols-4', 5: 'grid-cols-5', 6: 'grid-cols-6',
96
+ };
97
+ /** Container blocks expose nested child arrays (issue #1499). Returns each
98
+ * group's display label, the path suffix to its children array (relative to
99
+ * the block), and the current children. */
100
+ function childGroups(block) {
101
+ const props = block?.properties || {};
102
+ switch (block?.type) {
103
+ case 'page:tabs':
104
+ case 'page:accordion': {
105
+ const items = Array.isArray(props.items) ? props.items : [];
106
+ return items.map((it, i) => ({
107
+ label: it?.label || it?.key || `Item ${i + 1}`,
108
+ pathSuffix: `properties.items[${i}].children`,
109
+ children: Array.isArray(it?.children) ? it.children : [],
110
+ }));
111
+ }
112
+ case 'page:card': {
113
+ // Seeded cards nest under `properties.children`; older specs used
114
+ // `properties.body`. Prefer children, fall back to body so neither
115
+ // shape leaves the card's content unreachable on the canvas.
116
+ if (Array.isArray(props.body) && !Array.isArray(props.children)) {
117
+ return [{ label: 'Body', pathSuffix: 'properties.body', children: props.body }];
118
+ }
119
+ return [{ label: 'Body', pathSuffix: 'properties.children', children: Array.isArray(props.children) ? props.children : [] }];
120
+ }
121
+ case 'page:section':
122
+ case 'grid':
123
+ return [{ label: 'Content', pathSuffix: 'properties.children', children: Array.isArray(props.children) ? props.children : [] }];
124
+ default:
125
+ // Future-proof: any block carrying a `properties.children` array (e.g.
126
+ // `container`) exposes those children for selection/editing.
127
+ if (Array.isArray(props.children)) {
128
+ return [{ label: 'Content', pathSuffix: 'properties.children', children: props.children }];
129
+ }
130
+ return [];
131
+ }
132
+ }
133
+ /** Canonical record-page slots, in render order. A `kind:'slotted'` page
134
+ * overrides individual slots; unoverridden ones are filled by the synthesizer.
135
+ * We surface all of them so an author can override an inherited slot too. */
136
+ export const SLOT_ORDER = ['header', 'actions', 'alerts', 'highlights', 'details', 'tabs', 'discussion'];
137
+ /** slots object → one region per slot (single component normalised to array). */
138
+ export function slotsToRegions(slots) {
139
+ const s = slots || {};
140
+ return SLOT_ORDER.map((name) => {
141
+ const v = s[name];
142
+ const components = Array.isArray(v) ? v : v != null ? [v] : [];
143
+ return { name, components };
144
+ });
145
+ }
146
+ /** regions (one per slot) → slots object; empty slots are omitted (= inherited). */
147
+ export function regionsToSlots(regions) {
148
+ const slots = {};
149
+ for (const r of regions) {
150
+ const comps = Array.isArray(r.components) ? r.components : [];
151
+ if (comps.length === 0 || !r.name)
152
+ continue; // omit empty → inherit the default
153
+ slots[r.name] = comps;
154
+ }
155
+ return slots;
156
+ }
157
+ function readRegions(draft) {
158
+ // Slotted record page — edit the named slots (must win over an empty
159
+ // `regions: []`, which slotted pages carry).
160
+ const slots = draft.slots;
161
+ if (draft.kind === 'slotted' && slots && typeof slots === 'object' && !Array.isArray(slots)) {
162
+ return { regions: slotsToRegions(slots), shape: 'slots' };
163
+ }
164
+ const raw = draft.regions;
165
+ if (Array.isArray(raw))
166
+ return { regions: raw, shape: 'regions' };
167
+ const kids = draft.children;
168
+ if (Array.isArray(kids)) {
169
+ // Virtualise children[] as a single anonymous region.
170
+ return { regions: [{ name: 'children', components: kids }], shape: 'children' };
171
+ }
172
+ return { regions: [], shape: 'regions' };
173
+ }
174
+ /** Build a selection ID matching PageBlockInspector's parsePath regex.
175
+ * - regions shape: regions[i].components[j]
176
+ * - children shape: children[j] (flat, no nesting)
177
+ */
178
+ function selectionId(shape, regionIdx, compIdx, slotName) {
179
+ if (shape === 'children')
180
+ return `children[${compIdx}]`;
181
+ if (shape === 'slots')
182
+ return `slot:${slotName}:${compIdx}`;
183
+ return `regions[${regionIdx}].components[${compIdx}]`;
184
+ }
185
+ function blockLabel(b) {
186
+ return ((typeof b.label === 'string' && b.label) ||
187
+ (typeof b.title === 'string' && b.title) ||
188
+ (typeof b.id === 'string' && b.id) ||
189
+ String(b.type ?? 'block'));
190
+ }
191
+ const DT_MIME = 'text/x-objectui-pageblock';
192
+ export function PageBlockCanvas({ draft, onPatch, selection, onSelectionChange, }) {
193
+ const readOnly = !onPatch;
194
+ const { regions, shape } = React.useMemo(() => readRegions(draft), [draft]);
195
+ const selectedId = selection?.kind === 'block' ? String(selection.id) : null;
196
+ const writeRegions = React.useCallback((next) => {
197
+ if (shape === 'children') {
198
+ const comps = next.flatMap((r) => (Array.isArray(r.components) ? r.components : []));
199
+ onPatch?.({ children: comps });
200
+ }
201
+ else if (shape === 'slots') {
202
+ onPatch?.({ slots: regionsToSlots(next) });
203
+ }
204
+ else {
205
+ onPatch?.({ regions: next });
206
+ }
207
+ }, [onPatch, shape]);
208
+ /** Move a block from src path → dst region (append) or before/after target block. */
209
+ const moveBlock = React.useCallback((src, dst) => {
210
+ if (!onPatch)
211
+ return;
212
+ // Defensive copies — never mutate inputs.
213
+ const next = regions.map((r) => ({
214
+ ...r,
215
+ components: Array.isArray(r.components) ? [...r.components] : [],
216
+ }));
217
+ const srcComps = next[src.region]?.components;
218
+ if (!srcComps)
219
+ return;
220
+ const [moved] = srcComps.splice(src.comp, 1);
221
+ if (!moved)
222
+ return;
223
+ const dstComps = next[dst.region]?.components;
224
+ if (!dstComps)
225
+ return;
226
+ let insertAt = dstComps.length;
227
+ if ('appendEnd' in dst)
228
+ insertAt = dstComps.length;
229
+ else if (dst.before != null) {
230
+ // Adjust if moving within same region above the original
231
+ let idx = dst.before;
232
+ if (src.region === dst.region && src.comp < idx)
233
+ idx -= 1;
234
+ insertAt = idx;
235
+ }
236
+ else if (dst.after != null) {
237
+ let idx = dst.after + 1;
238
+ if (src.region === dst.region && src.comp < dst.after + 1)
239
+ idx -= 1;
240
+ insertAt = idx;
241
+ }
242
+ dstComps.splice(insertAt, 0, moved);
243
+ writeRegions(next);
244
+ // Re-issue selection so inspector follows the move.
245
+ const newId = selectionId(shape, dst.region, insertAt, next[dst.region]?.name);
246
+ onSelectionChange?.({ kind: 'block', id: newId, label: blockLabel(moved) });
247
+ }, [onPatch, onSelectionChange, regions, writeRegions, shape]);
248
+ const addBlock = React.useCallback((regionIdx, type) => {
249
+ if (!onPatch)
250
+ return;
251
+ const next = regions.map((r) => ({
252
+ ...r,
253
+ components: Array.isArray(r.components) ? [...r.components] : [],
254
+ }));
255
+ if (!next[regionIdx]) {
256
+ next[regionIdx] = { name: `region_${regionIdx + 1}`, components: [] };
257
+ }
258
+ const newBlock = { type };
259
+ next[regionIdx].components.push(newBlock);
260
+ writeRegions(next);
261
+ const idx = next[regionIdx].components.length - 1;
262
+ onSelectionChange?.({
263
+ kind: 'block',
264
+ id: selectionId(shape, regionIdx, idx, next[regionIdx]?.name),
265
+ label: blockLabel(newBlock),
266
+ });
267
+ }, [onPatch, onSelectionChange, regions, writeRegions, shape]);
268
+ const renameLabel = React.useCallback((regionIdx, compIdx, nextLabel) => {
269
+ if (!onPatch)
270
+ return;
271
+ const next = regions.map((r) => ({
272
+ ...r,
273
+ components: Array.isArray(r.components) ? [...r.components] : [],
274
+ }));
275
+ const target = next[regionIdx]?.components?.[compIdx];
276
+ if (!target)
277
+ return;
278
+ next[regionIdx].components[compIdx] = { ...target, label: nextLabel || undefined };
279
+ writeRegions(next);
280
+ }, [onPatch, regions, writeRegions]);
281
+ const addRegion = React.useCallback(() => {
282
+ if (!onPatch)
283
+ return;
284
+ const next = [...regions, { name: `region_${regions.length + 1}`, components: [] }];
285
+ writeRegions(next);
286
+ }, [onPatch, regions, writeRegions]);
287
+ // Append a block into a container's nested child array (issue #1499).
288
+ // `baseId` is the container's selection id (`regions[r].components[c]` or
289
+ // `slot:<name>:<idx>`); `pathSuffix` locates the children array within it.
290
+ const addNestedBlock = React.useCallback((baseId, pathSuffix, type) => {
291
+ if (!onPatch)
292
+ return;
293
+ const slot = /^slot:([a-zA-Z_]+):(\d+)$/.exec(baseId);
294
+ const subHops = parsePath(pathSuffix);
295
+ if (!subHops)
296
+ return;
297
+ const subPath = hopsToPath(subHops);
298
+ if (slot) {
299
+ const name = slot[1];
300
+ const idx = Number(slot[2]);
301
+ const slots = (draft.slots || {});
302
+ const v = slots[name];
303
+ const arr = Array.isArray(v) ? [...v] : v != null ? [v] : [];
304
+ const base = arr[idx];
305
+ if (!base)
306
+ return;
307
+ const cur = getByPath(base, subPath) || [];
308
+ arr[idx] = setByPath(base, subPath, [...cur, { type }]);
309
+ onPatch({ slots: { ...slots, [name]: arr } });
310
+ onSelectionChange?.({ kind: 'block', id: `${baseId}.${pathSuffix}[${cur.length}]`, label: type });
311
+ }
312
+ else {
313
+ const fullHops = parsePath(`${baseId}.${pathSuffix}`);
314
+ if (!fullHops)
315
+ return;
316
+ const fullPath = hopsToPath(fullHops);
317
+ const cur = getByPath(draft, fullPath) || [];
318
+ const next = setByPath(draft, fullPath, [...cur, { type }]);
319
+ onPatch({ [fullPath[0]]: next[fullPath[0]] });
320
+ onSelectionChange?.({ kind: 'block', id: `${baseId}.${pathSuffix}[${cur.length}]`, label: type });
321
+ }
322
+ }, [onPatch, draft, onSelectionChange]);
323
+ const handleBgClick = React.useCallback((e) => {
324
+ if (e.target === e.currentTarget && selectedId)
325
+ onSelectionChange?.(null);
326
+ }, [onSelectionChange, selectedId]);
327
+ // Empty draft → empty canvas with hint. (ADR-0047 interface pages never
328
+ // reach this canvas — PagePreview renders them as a live InterfaceListPage
329
+ // in both design and preview modes — so no interface-specific hint here.)
330
+ if (regions.length === 0) {
331
+ return (_jsx("div", { className: "h-full overflow-auto bg-muted/20", onClick: handleBgClick, children: _jsx("div", { className: "mx-auto max-w-3xl px-6 py-8", children: _jsxs("div", { className: "rounded-lg border-2 border-dashed bg-background py-16 px-6 text-center space-y-3", children: [_jsx("div", { className: "text-sm font-medium", children: "No regions yet" }), _jsx("div", { className: "text-xs text-muted-foreground", children: "A Page is composed of regions (header / main / sidebar / \u2026). Add a region to start dropping blocks into it." }), !readOnly && (_jsx("div", { className: "pt-2", children: _jsxs(Button, { variant: "outline", size: "sm", className: "gap-1.5 border-dashed", onClick: addRegion, children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Add region"] }) }))] }) }) }));
332
+ }
333
+ return (_jsx("div", { className: "h-full overflow-auto bg-muted/20", onClick: handleBgClick, children: _jsxs("div", { className: "mx-auto max-w-3xl px-6 py-6 space-y-5", onClick: handleBgClick, children: [regions.map((region, regionIdx) => (_jsx(RegionSection, { region: region, regionIdx: regionIdx, shape: shape, selectedId: selectedId, readOnly: readOnly, onSelectBlock: (compIdx, blk) => onSelectionChange?.({
334
+ kind: 'block',
335
+ id: selectionId(shape, regionIdx, compIdx, region.name),
336
+ label: blockLabel(blk),
337
+ }), onMoveBlock: moveBlock, onAddBlock: addBlock, onRenameLabel: renameLabel, baseIdOf: (compIdx) => selectionId(shape, regionIdx, compIdx, region.name), onSelectId: (sid, lbl) => onSelectionChange?.({ kind: 'block', id: sid, label: lbl }), onAddNested: addNestedBlock }, regionIdx))), !readOnly && shape === 'regions' && (_jsx("div", { className: "pt-1", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "gap-1.5 text-muted-foreground", onClick: addRegion, children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Add region"] }) }))] }) }));
338
+ }
339
+ /* ─────────────── Region section ─────────────── */
340
+ function RegionSection({ region, regionIdx, shape, selectedId, readOnly, onSelectBlock, onMoveBlock, onAddBlock, onRenameLabel, onSelectId, onAddNested, }) {
341
+ const comps = Array.isArray(region.components) ? region.components : [];
342
+ const [active, setActive] = React.useState(false);
343
+ const handleDragOver = (e) => {
344
+ if (readOnly)
345
+ return;
346
+ const types = e.dataTransfer.types;
347
+ if (!types || !Array.from(types).includes(DT_MIME))
348
+ return;
349
+ e.preventDefault();
350
+ e.dataTransfer.dropEffect = 'move';
351
+ setActive(true);
352
+ };
353
+ const handleDragLeave = (e) => {
354
+ if (e.currentTarget === e.target)
355
+ setActive(false);
356
+ };
357
+ const handleDrop = (e) => {
358
+ if (readOnly)
359
+ return;
360
+ setActive(false);
361
+ if (e.defaultPrevented)
362
+ return;
363
+ e.preventDefault();
364
+ const raw = e.dataTransfer.getData(DT_MIME);
365
+ if (!raw)
366
+ return;
367
+ try {
368
+ const src = JSON.parse(raw);
369
+ if (typeof src.region !== 'number' || typeof src.comp !== 'number')
370
+ return;
371
+ onMoveBlock(src, { region: regionIdx, appendEnd: true });
372
+ }
373
+ catch { /* ignore */ }
374
+ };
375
+ return (_jsxs("section", { className: cn('rounded-md transition-colors', active && 'bg-primary/5 ring-1 ring-primary/30 -mx-1 px-1 py-1'), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [_jsxs("div", { className: "text-[11px] font-medium uppercase tracking-wider text-muted-foreground pl-1 mb-2 flex items-center gap-2", children: [_jsx("span", { children: region.name || `region ${regionIdx + 1}` }), region.width && (_jsxs("span", { className: "normal-case text-[10px] text-muted-foreground/60", children: ["\u00B7 ", region.width] })), active && _jsx("span", { className: "text-primary normal-case text-[10px]", children: "drop here" })] }), _jsxs("div", { className: "space-y-2.5", children: [comps.length === 0 ? (_jsx("div", { className: "rounded border border-dashed bg-background/50 py-6 px-4 text-center text-xs text-muted-foreground", children: shape === 'slots'
376
+ ? 'Inherited from the default page — add a block to override this slot.'
377
+ : 'Empty region — drop a block here or use the add button below.' })) : (comps.map((blk, compIdx) => {
378
+ const id = selectionId(shape, regionIdx, compIdx, region.name);
379
+ return (_jsxs(React.Fragment, { children: [_jsx(BlockRow, { block: blk, regionIdx: regionIdx, compIdx: compIdx, selected: id === selectedId, readOnly: readOnly, onClick: () => onSelectBlock(compIdx, blk), onMoveBlock: onMoveBlock, onRenameLabel: (v) => onRenameLabel(regionIdx, compIdx, v) }), _jsx(NestedChildren, { block: blk, baseId: id, selectedId: selectedId, readOnly: readOnly, onSelectId: onSelectId, onAddNested: onAddNested })] }, `${regionIdx}:${compIdx}`));
380
+ })), !readOnly && (_jsx("div", { className: "pt-1", children: _jsx(AddBlockButton, { onPick: (type) => onAddBlock(regionIdx, type) }) }))] })] }));
381
+ }
382
+ /* ─────────────── Block row ─────────────── */
383
+ function BlockRow({ block, regionIdx, compIdx, selected, readOnly, onClick, onMoveBlock, onRenameLabel, }) {
384
+ const typeStr = String(block.type ?? '');
385
+ const meta = BLOCK_TYPE_META[typeStr];
386
+ const Icon = meta?.Icon ?? UnknownBlockIcon;
387
+ const tone = resolveBlockTone(typeStr);
388
+ const label = blockLabel(block);
389
+ const draggable = !readOnly;
390
+ const [dropZone, setDropZone] = React.useState(null);
391
+ const handleDragStart = (e) => {
392
+ e.dataTransfer.setData(DT_MIME, JSON.stringify({ region: regionIdx, comp: compIdx }));
393
+ e.dataTransfer.effectAllowed = 'move';
394
+ };
395
+ const handleDragOver = (e) => {
396
+ if (!draggable)
397
+ return;
398
+ const types = e.dataTransfer.types;
399
+ if (!types || !Array.from(types).includes(DT_MIME))
400
+ return;
401
+ e.preventDefault();
402
+ e.dataTransfer.dropEffect = 'move';
403
+ const rect = e.currentTarget.getBoundingClientRect();
404
+ setDropZone(e.clientY - rect.top < rect.height / 2 ? 'before' : 'after');
405
+ };
406
+ const handleDragLeave = () => setDropZone(null);
407
+ const handleDrop = (e) => {
408
+ if (readOnly)
409
+ return;
410
+ e.preventDefault();
411
+ e.stopPropagation();
412
+ const pos = dropZone ?? 'before';
413
+ setDropZone(null);
414
+ const raw = e.dataTransfer.getData(DT_MIME);
415
+ if (!raw)
416
+ return;
417
+ try {
418
+ const src = JSON.parse(raw);
419
+ if (src.region === regionIdx && src.comp === compIdx)
420
+ return;
421
+ const dst = pos === 'before'
422
+ ? { region: regionIdx, before: compIdx }
423
+ : { region: regionIdx, after: compIdx };
424
+ onMoveBlock(src, dst);
425
+ }
426
+ catch { /* ignore */ }
427
+ };
428
+ // Inline label rename
429
+ const [editingLabel, setEditingLabel] = React.useState(false);
430
+ const [draft, setDraft] = React.useState(label);
431
+ React.useEffect(() => { setDraft(label); }, [label]);
432
+ const beginEdit = (e) => {
433
+ if (readOnly)
434
+ return;
435
+ e.preventDefault();
436
+ e.stopPropagation();
437
+ setDraft(label);
438
+ setEditingLabel(true);
439
+ };
440
+ const commitEdit = () => {
441
+ if (readOnly) {
442
+ setEditingLabel(false);
443
+ return;
444
+ }
445
+ const next = draft.trim();
446
+ if (next && next !== label)
447
+ onRenameLabel(next);
448
+ setEditingLabel(false);
449
+ };
450
+ const cancelEdit = () => { setDraft(label); setEditingLabel(false); };
451
+ // Container blocks (grid / card / tabs / section) render a slim title bar —
452
+ // their real content is the nested child cards shown below by NestedChildren.
453
+ // Leaf blocks render their REAL component so the canvas mirrors the preview.
454
+ const isContainer = childGroups(block).length > 0;
455
+ return (_jsxs("div", { className: cn('relative', dropZone === 'before' && 'pt-1.5'), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [dropZone === 'before' && (_jsx("div", { className: "absolute left-0 right-0 -top-0.5 h-0.5 bg-primary rounded-full" })), _jsx("div", { className: cn('group relative rounded-md border bg-card transition-colors hover:border-primary/40', selected ? 'border-primary ring-2 ring-primary/30 shadow-sm' : 'border-border'), children: isContainer ? (_jsxs("button", { type: "button", onClick: onClick, draggable: draggable, onDragStart: handleDragStart, className: cn('flex w-full items-center justify-between gap-2 rounded-md px-3.5 py-2.5 text-left', readOnly && 'cursor-default', draggable && 'cursor-grab active:cursor-grabbing'), "aria-pressed": selected, children: [_jsxs("div", { className: "flex items-center gap-1.5 min-w-0 flex-1", children: [draggable && (_jsx(GripVertical, { className: "h-3.5 w-3.5 text-muted-foreground/40 shrink-0 group-hover:text-muted-foreground/80", "aria-hidden": "true" })), _jsx(Icon, { className: cn('h-3.5 w-3.5 shrink-0', tone.icon) }), editingLabel ? (_jsx("input", { autoFocus: true, value: draft, onChange: (e) => setDraft(e.target.value), onClick: (e) => e.stopPropagation(), onKeyDown: (e) => {
456
+ e.stopPropagation();
457
+ if (e.key === 'Enter') {
458
+ e.preventDefault();
459
+ commitEdit();
460
+ }
461
+ else if (e.key === 'Escape') {
462
+ e.preventDefault();
463
+ cancelEdit();
464
+ }
465
+ }, onBlur: commitEdit, className: "text-sm font-medium px-1 py-0.5 -mx-1 -my-0.5 rounded border border-primary bg-background outline-none min-w-0 flex-1" })) : (_jsx("span", { className: cn('text-sm font-medium truncate', !readOnly && 'cursor-text'), onDoubleClick: beginEdit, title: !readOnly ? 'Double-click to rename' : undefined, children: label })), block.id && block.id !== label && (_jsxs("code", { className: "text-[10px] text-muted-foreground/70 font-mono truncate", children: ["#", block.id] }))] }), _jsx(Badge, { variant: "outline", className: cn('text-[10px] shrink-0 font-mono', tone.badge), children: typeStr })] })) : (_jsxs(_Fragment, { children: [_jsx(BlockLivePreview, { block: block }), _jsx("button", { type: "button", onClick: onClick, draggable: draggable, onDragStart: handleDragStart, "aria-label": `Select ${label}`, "aria-pressed": selected, className: cn('absolute inset-0 z-10 rounded-md', readOnly && 'cursor-default', draggable && 'cursor-grab active:cursor-grabbing') }), _jsxs("div", { className: cn('pointer-events-none absolute right-1.5 top-1.5 z-20 flex items-center gap-1 transition-opacity', selected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'), children: [draggable && _jsx(GripVertical, { className: "h-3.5 w-3.5 text-muted-foreground/60", "aria-hidden": "true" }), _jsx(Badge, { variant: "outline", className: cn('text-[10px] font-mono shadow-sm bg-background/90 backdrop-blur', tone.badge), children: typeStr })] })] })) }), dropZone === 'after' && (_jsx("div", { className: "absolute left-0 right-0 -bottom-1 h-0.5 bg-primary rounded-full" }))] }));
466
+ }
467
+ /* ─────────────── Nested container children (issue #1499) ─────────────── */
468
+ function NestedChildren({ block, baseId, selectedId, readOnly, onSelectId, onAddNested, }) {
469
+ const groups = childGroups(block);
470
+ if (groups.length === 0)
471
+ return null;
472
+ // A grid lays its children in N columns at runtime — mirror that here so the
473
+ // design canvas matches the preview (other containers stack in one column).
474
+ const gridCols = block?.type === 'grid'
475
+ ? Math.min(6, Math.max(1, Number(block.properties?.columns) || 1))
476
+ : 1;
477
+ const colsClass = GRID_COLS_CLASS[gridCols] ?? 'grid-cols-1';
478
+ return (_jsx("div", { className: "ml-5 mt-1.5 space-y-2.5 border-l border-dashed border-border pl-3", children: groups.map((g, gi) => (_jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70", children: g.label }), g.children.length === 0 ? (_jsx("div", { className: "rounded border border-dashed bg-background/40 py-2 px-3 text-[11px] text-muted-foreground", children: "Empty \u2014 add a block." })) : (_jsx("div", { className: cn('grid gap-2', colsClass), children: g.children.map((child, ci) => {
479
+ const cid = `${baseId}.${g.pathSuffix}[${ci}]`;
480
+ const typeStr = String(child?.type ?? '');
481
+ const childSelected = cid === selectedId;
482
+ return (_jsxs("div", { className: cn('group relative rounded-md border bg-card transition-colors hover:border-primary/40', childSelected ? 'border-primary ring-2 ring-primary/30 shadow-sm' : 'border-border'), children: [_jsx(BlockLivePreview, { block: child, maxHeightClass: "max-h-56" }), _jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); onSelectId(cid, blockLabel(child)); }, "aria-label": `Select ${blockLabel(child)}`, "aria-pressed": childSelected, className: "absolute inset-0 z-10 rounded-md cursor-pointer" }), _jsx("div", { className: cn('pointer-events-none absolute right-1.5 top-1.5 z-20 transition-opacity', childSelected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'), children: _jsx(Badge, { variant: "outline", className: cn('text-[10px] font-mono shadow-sm bg-background/90 backdrop-blur', resolveBlockTone(typeStr).badge), children: typeStr }) })] }, ci));
483
+ }) })), !readOnly && _jsx(AddBlockButton, { onPick: (type) => onAddNested(baseId, g.pathSuffix, type) })] }, gi))) }));
484
+ }
485
+ /* ─────────────── Add block picker ─────────────── */
486
+ function AddBlockButton({ onPick }) {
487
+ const [open, setOpen] = React.useState(false);
488
+ const [filter, setFilter] = React.useState('');
489
+ const q = filter.trim().toLowerCase();
490
+ const groups = React.useMemo(() => {
491
+ if (!q)
492
+ return TYPES_BY_CATEGORY;
493
+ return TYPES_BY_CATEGORY
494
+ .map((g) => ({
495
+ category: g.category,
496
+ types: g.types.filter((id) => {
497
+ const m = BLOCK_TYPE_META[id];
498
+ return id.includes(q) || m.label.toLowerCase().includes(q);
499
+ }),
500
+ }))
501
+ .filter((g) => g.types.length > 0);
502
+ }, [q]);
503
+ return (_jsxs(Popover, { open: open, onOpenChange: (o) => { setOpen(o); if (!o)
504
+ setFilter(''); }, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", className: "gap-1.5 border-dashed", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Add block"] }) }), _jsxs(PopoverContent, { align: "start", className: "w-[320px] p-0 max-h-[480px] overflow-hidden flex flex-col", children: [_jsx("div", { className: "p-2 border-b", children: _jsx("input", { autoFocus: true, value: filter, onChange: (e) => setFilter(e.target.value), placeholder: "Search block type\u2026", className: "h-7 w-full px-2 text-sm border rounded bg-background outline-none focus:ring-1 focus:ring-primary" }) }), _jsx("div", { className: "flex-1 overflow-auto p-1", children: groups.length === 0 ? (_jsx("div", { className: "text-xs text-muted-foreground p-4 text-center", children: "No matching types." })) : (groups.map((g) => (_jsxs("div", { className: "mb-1", children: [_jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground px-2 py-1", children: CATEGORY_LABEL_EN[g.category] }), g.types.map((id) => {
505
+ const m = BLOCK_TYPE_META[id];
506
+ const Icon = m.Icon;
507
+ const tone = resolveBlockTone(id);
508
+ return (_jsxs("button", { type: "button", onClick: () => { onPick(id); setOpen(false); setFilter(''); }, className: "w-full flex items-center gap-2 px-2 py-1.5 rounded text-sm hover:bg-accent text-left", children: [_jsx(Icon, { className: cn('h-3.5 w-3.5 shrink-0', tone.icon) }), _jsx("span", { className: "truncate", children: m.label }), _jsx("code", { className: "ml-auto text-[10px] text-muted-foreground/70 font-mono truncate", children: id })] }, id));
509
+ })] }, g.category)))) })] })] }));
510
+ }
@@ -1,2 +1,11 @@
1
+ /**
2
+ * PagePreview — renders a Page metadata record using the runtime
3
+ * SchemaRenderer so authors see exactly what end-users would see.
4
+ *
5
+ * Reads the live draft (not the server-saved record) so edits in the
6
+ * Form tab preview instantly. URL query params are intentionally not
7
+ * threaded in: previews run in a sandbox with no params context.
8
+ */
9
+ import * as React from 'react';
1
10
  import type { MetadataPreviewProps } from '../preview-registry';
2
- export declare function PagePreview({ draft }: MetadataPreviewProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function PagePreview({ draft, editing, selection, onSelectionChange, onPatch, locale }: MetadataPreviewProps): React.JSX.Element;