@manta-eu/react 0.2.0 → 0.3.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 (324) hide show
  1. package/dist/components/channel-icon/index.d.ts +1 -0
  2. package/dist/components/channel-icon/index.d.ts.map +1 -1
  3. package/dist/components/channel-icon/index.js +1 -1
  4. package/dist/components/channel-icon/index.js.map +1 -1
  5. package/dist/components/datastore-management/tree.d.ts +1 -1
  6. package/dist/components/datastore-management/tree.d.ts.map +1 -1
  7. package/dist/components/datastore-management/tree.js +5 -5
  8. package/dist/components/datastore-management/tree.js.map +1 -1
  9. package/dist/components/explain-fact/ExplainFact.js +3 -3
  10. package/dist/components/explain-fact/ExplainFact.js.map +1 -1
  11. package/dist/components/planning/ActioningView.d.ts +1 -2
  12. package/dist/components/planning/ActioningView.d.ts.map +1 -1
  13. package/dist/components/planning/ActioningView.js +19 -44
  14. package/dist/components/planning/ActioningView.js.map +1 -1
  15. package/dist/components/planning/ManualActionCard.d.ts +4 -0
  16. package/dist/components/planning/ManualActionCard.d.ts.map +1 -1
  17. package/dist/components/planning/ManualActionCard.js +7 -5
  18. package/dist/components/planning/ManualActionCard.js.map +1 -1
  19. package/dist/components/planning/ManualActionList.d.ts +4 -0
  20. package/dist/components/planning/ManualActionList.d.ts.map +1 -1
  21. package/dist/components/planning/ManualActionList.js +8 -2
  22. package/dist/components/planning/ManualActionList.js.map +1 -1
  23. package/dist/components/planning/actioning-view-utils.d.ts +9 -0
  24. package/dist/components/planning/actioning-view-utils.d.ts.map +1 -1
  25. package/dist/components/planning/actioning-view-utils.js +19 -1
  26. package/dist/components/planning/actioning-view-utils.js.map +1 -1
  27. package/dist/components/planning/plan-detail-utils.d.ts.map +1 -1
  28. package/dist/components/planning/plan-detail-utils.js +2 -0
  29. package/dist/components/planning/plan-detail-utils.js.map +1 -1
  30. package/dist/components/tool-invocation-card/ListRulesResultDisplay.d.ts +2 -2
  31. package/dist/components/tool-invocation-card/ListRulesResultDisplay.d.ts.map +1 -1
  32. package/dist/components/tool-invocation-card/ToolOutputRenderer.d.ts.map +1 -1
  33. package/dist/components/tool-invocation-card/ToolOutputRenderer.js +7 -4
  34. package/dist/components/tool-invocation-card/ToolOutputRenderer.js.map +1 -1
  35. package/dist/components/tool-invocation-card/types.d.ts +5 -5
  36. package/dist/components/tool-invocation-card/types.d.ts.map +1 -1
  37. package/dist/components/tool-invocation-card/types.js +5 -5
  38. package/dist/components/tool-invocation-card/types.js.map +1 -1
  39. package/dist/components/tooltip/index.d.ts +7 -0
  40. package/dist/components/tooltip/index.d.ts.map +1 -1
  41. package/dist/components/tooltip/index.js +10 -1
  42. package/dist/components/tooltip/index.js.map +1 -1
  43. package/dist/explain-fact/rule-presentation.js +2 -2
  44. package/dist/explain-fact/rule-presentation.js.map +1 -1
  45. package/dist/explain-fact/tree-model.js +2 -2
  46. package/dist/explain-fact/tree-model.js.map +1 -1
  47. package/dist/globals.css +19 -6
  48. package/dist/graph/entity-link.d.ts +14 -0
  49. package/dist/graph/entity-link.d.ts.map +1 -0
  50. package/dist/graph/entity-link.js +12 -0
  51. package/dist/graph/entity-link.js.map +1 -0
  52. package/dist/graph/graph-list-utils.d.ts +1 -0
  53. package/dist/graph/graph-list-utils.d.ts.map +1 -1
  54. package/dist/graph/graph-list-utils.js +1 -0
  55. package/dist/graph/graph-list-utils.js.map +1 -1
  56. package/dist/graph/graph-model.d.ts.map +1 -1
  57. package/dist/graph/graph-model.js +14 -5
  58. package/dist/graph/graph-model.js.map +1 -1
  59. package/dist/graph/nodes/BrandAssetAnalysisView.d.ts.map +1 -1
  60. package/dist/graph/nodes/BrandAssetAnalysisView.js +2 -1
  61. package/dist/graph/nodes/BrandAssetAnalysisView.js.map +1 -1
  62. package/dist/graph/nodes/BrandFontSuggestionView.d.ts.map +1 -1
  63. package/dist/graph/nodes/BrandFontSuggestionView.js +2 -1
  64. package/dist/graph/nodes/BrandFontSuggestionView.js.map +1 -1
  65. package/dist/graph/nodes/BrandGuidelinesView.js +1 -1
  66. package/dist/graph/nodes/BrandGuidelinesView.js.map +1 -1
  67. package/dist/graph/nodes/NodePropertyTable.d.ts +4 -2
  68. package/dist/graph/nodes/NodePropertyTable.d.ts.map +1 -1
  69. package/dist/graph/nodes/NodePropertyTable.js +12 -59
  70. package/dist/graph/nodes/NodePropertyTable.js.map +1 -1
  71. package/dist/graph/nodes/node-property-row.d.ts +30 -0
  72. package/dist/graph/nodes/node-property-row.d.ts.map +1 -0
  73. package/dist/graph/nodes/node-property-row.js +35 -0
  74. package/dist/graph/nodes/node-property-row.js.map +1 -0
  75. package/dist/graph/property-formatters.d.ts +1 -0
  76. package/dist/graph/property-formatters.d.ts.map +1 -1
  77. package/dist/graph/property-formatters.js +4 -1
  78. package/dist/graph/property-formatters.js.map +1 -1
  79. package/dist/graph/special-nodes/AttributeList.d.ts +27 -0
  80. package/dist/graph/special-nodes/AttributeList.d.ts.map +1 -0
  81. package/dist/graph/special-nodes/AttributeList.js +57 -0
  82. package/dist/graph/special-nodes/AttributeList.js.map +1 -0
  83. package/dist/graph/special-nodes/EntityPreview.d.ts +5 -0
  84. package/dist/graph/special-nodes/EntityPreview.d.ts.map +1 -0
  85. package/dist/graph/special-nodes/EntityPreview.js +19 -0
  86. package/dist/graph/special-nodes/EntityPreview.js.map +1 -0
  87. package/dist/graph/special-nodes/EntityValueChip.d.ts +11 -0
  88. package/dist/graph/special-nodes/EntityValueChip.d.ts.map +1 -0
  89. package/dist/graph/special-nodes/EntityValueChip.js +40 -0
  90. package/dist/graph/special-nodes/EntityValueChip.js.map +1 -0
  91. package/dist/graph/special-nodes/GenericView.d.ts +2 -1
  92. package/dist/graph/special-nodes/GenericView.d.ts.map +1 -1
  93. package/dist/graph/special-nodes/GenericView.js +23 -69
  94. package/dist/graph/special-nodes/GenericView.js.map +1 -1
  95. package/dist/graph/special-nodes/card-facts.d.ts +52 -0
  96. package/dist/graph/special-nodes/card-facts.d.ts.map +1 -0
  97. package/dist/graph/special-nodes/card-facts.js +189 -0
  98. package/dist/graph/special-nodes/card-facts.js.map +1 -0
  99. package/dist/graph/special-nodes/property-icons.d.ts +9 -0
  100. package/dist/graph/special-nodes/property-icons.d.ts.map +1 -0
  101. package/dist/graph/special-nodes/property-icons.js +39 -0
  102. package/dist/graph/special-nodes/property-icons.js.map +1 -0
  103. package/dist/graph/status-utils.d.ts +16 -0
  104. package/dist/graph/status-utils.d.ts.map +1 -1
  105. package/dist/graph/status-utils.js +35 -0
  106. package/dist/graph/status-utils.js.map +1 -1
  107. package/dist/graph/types.d.ts +5 -0
  108. package/dist/graph/types.d.ts.map +1 -1
  109. package/dist/hooks/use-approve-anyway.d.ts +12 -0
  110. package/dist/hooks/use-approve-anyway.d.ts.map +1 -0
  111. package/dist/hooks/use-approve-anyway.js +81 -0
  112. package/dist/hooks/use-approve-anyway.js.map +1 -0
  113. package/dist/hooks/use-connection-problems.d.ts.map +1 -1
  114. package/dist/hooks/useValidateActionPlan.d.ts.map +1 -1
  115. package/dist/ldo-ui.d.ts +2 -1
  116. package/dist/ldo-ui.d.ts.map +1 -1
  117. package/dist/ldo-ui.js +1 -0
  118. package/dist/ldo-ui.js.map +1 -1
  119. package/dist/lib/find-latest-staged-rule.js +1 -1
  120. package/dist/lib/find-latest-staged-rule.js.map +1 -1
  121. package/dist/lib/manual-actions.d.ts +2 -1
  122. package/dist/lib/manual-actions.d.ts.map +1 -1
  123. package/dist/lib/manual-actions.js +3 -2
  124. package/dist/lib/manual-actions.js.map +1 -1
  125. package/dist/lib/tool-icons.js +6 -6
  126. package/dist/lib/tool-icons.js.map +1 -1
  127. package/dist/lib/tool-names.d.ts.map +1 -1
  128. package/dist/lib/tool-names.js +0 -1
  129. package/dist/lib/tool-names.js.map +1 -1
  130. package/dist/ontology/skolem.js +2 -2
  131. package/dist/ontology/skolem.js.map +1 -1
  132. package/dist/providers/ActiveChatProvider.js +3 -1
  133. package/dist/providers/ActiveChatProvider.js.map +1 -1
  134. package/dist/providers/ChatManagerProvider.d.ts.map +1 -1
  135. package/dist/providers/ChatManagerProvider.js +3 -1
  136. package/dist/providers/ChatManagerProvider.js.map +1 -1
  137. package/dist/providers/KnowledgeGraphStateProvider.js +1 -1
  138. package/dist/providers/KnowledgeGraphStateProvider.js.map +1 -1
  139. package/dist/providers/chat-socket-auth.d.ts +7 -2
  140. package/dist/providers/chat-socket-auth.d.ts.map +1 -1
  141. package/dist/providers/chat-socket-auth.js +87 -16
  142. package/dist/providers/chat-socket-auth.js.map +1 -1
  143. package/dist/providers/index.d.ts.map +1 -1
  144. package/dist/providers/index.js +8 -1
  145. package/dist/providers/index.js.map +1 -1
  146. package/dist/routes/activity/detail/ActivityChanges.d.ts +2 -0
  147. package/dist/routes/activity/detail/ActivityChanges.d.ts.map +1 -1
  148. package/dist/routes/activity/detail/ActivityChanges.js +8 -7
  149. package/dist/routes/activity/detail/ActivityChanges.js.map +1 -1
  150. package/dist/routes/activity/detail/ActivityDetail.d.ts +1 -0
  151. package/dist/routes/activity/detail/ActivityDetail.d.ts.map +1 -1
  152. package/dist/routes/activity/detail/ActivityDetail.js +5 -4
  153. package/dist/routes/activity/detail/ActivityDetail.js.map +1 -1
  154. package/dist/routes/activity/detail/ActivityStepsRail.d.ts +1 -0
  155. package/dist/routes/activity/detail/ActivityStepsRail.d.ts.map +1 -1
  156. package/dist/routes/activity/detail/ActivityStepsRail.js +3 -2
  157. package/dist/routes/activity/detail/ActivityStepsRail.js.map +1 -1
  158. package/dist/routes/activity/detail/ActivityTimeline.js +2 -2
  159. package/dist/routes/activity/detail/ActivityTimeline.js.map +1 -1
  160. package/dist/routes/activity/detail/NoChangesMessage.d.ts +6 -0
  161. package/dist/routes/activity/detail/NoChangesMessage.d.ts.map +1 -0
  162. package/dist/routes/activity/detail/NoChangesMessage.js +10 -0
  163. package/dist/routes/activity/detail/NoChangesMessage.js.map +1 -0
  164. package/dist/routes/data-explorer/class-properties.js +2 -2
  165. package/dist/routes/data-explorer/class-properties.js.map +1 -1
  166. package/dist/routes/data-explorer/classes.js +2 -2
  167. package/dist/routes/data-explorer/classes.js.map +1 -1
  168. package/dist/routes/data-explorer/components/RawTriples.js +1 -1
  169. package/dist/routes/data-explorer/components/RawTriples.js.map +1 -1
  170. package/dist/routes/data-explorer/components/RecentTypes.js +1 -1
  171. package/dist/routes/data-explorer/components/RecentTypes.js.map +1 -1
  172. package/dist/routes/data-explorer/components/class-detail/Instances.js +1 -1
  173. package/dist/routes/data-explorer/components/class-detail/Instances.js.map +1 -1
  174. package/dist/routes/data-explorer/components/namespace-detail/NamespaceClassRow.js +1 -1
  175. package/dist/routes/data-explorer/components/namespace-detail/NamespaceClassRow.js.map +1 -1
  176. package/dist/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.js +1 -1
  177. package/dist/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.js.map +1 -1
  178. package/dist/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.js +1 -1
  179. package/dist/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.js.map +1 -1
  180. package/dist/routes/data-explorer/components/record-detail/ChatPreview.js +2 -2
  181. package/dist/routes/data-explorer/components/record-detail/ChatPreview.js.map +1 -1
  182. package/dist/routes/data-explorer/recents.js +1 -1
  183. package/dist/routes/data-explorer/recents.js.map +1 -1
  184. package/dist/routes/data-explorer/shapes.js +2 -2
  185. package/dist/routes/data-explorer/shapes.js.map +1 -1
  186. package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.d.ts +3 -0
  187. package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.d.ts.map +1 -0
  188. package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.js +12 -0
  189. package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.js.map +1 -0
  190. package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.d.ts.map +1 -1
  191. package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.js +13 -6
  192. package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.js.map +1 -1
  193. package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts +3 -0
  194. package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts.map +1 -1
  195. package/dist/routes/integrations/components/connect-forms/data-connection-fields.js +9 -2
  196. package/dist/routes/integrations/components/connect-forms/data-connection-fields.js.map +1 -1
  197. package/dist/routes/integrations/connect-forms.d.ts +1 -0
  198. package/dist/routes/integrations/connect-forms.d.ts.map +1 -1
  199. package/dist/routes/integrations/connect-forms.js +1 -0
  200. package/dist/routes/integrations/connect-forms.js.map +1 -1
  201. package/dist/routes/integrations/connection-view.d.ts.map +1 -1
  202. package/dist/routes/integrations/connection-view.js +1 -0
  203. package/dist/routes/integrations/connection-view.js.map +1 -1
  204. package/dist/routes/integrations/types.d.ts +2 -1
  205. package/dist/routes/integrations/types.d.ts.map +1 -1
  206. package/dist/routes/integrations/types.js +1 -0
  207. package/dist/routes/integrations/types.js.map +1 -1
  208. package/dist/routes/plans/components/ActionPlanPage.d.ts.map +1 -1
  209. package/dist/routes/plans/components/ActionPlanPage.js +4 -7
  210. package/dist/routes/plans/components/ActionPlanPage.js.map +1 -1
  211. package/dist/routes/plans/components/PlanDetailRouteContent.d.ts.map +1 -1
  212. package/dist/routes/plans/components/PlanDetailRouteContent.js +2 -1
  213. package/dist/routes/plans/components/PlanDetailRouteContent.js.map +1 -1
  214. package/dist/routes/rules/hooks/useRuleFactsPreview.js +4 -4
  215. package/dist/routes/rules/hooks/useRuleFactsPreview.js.map +1 -1
  216. package/dist/shacl/form-appearance.d.ts +1 -1
  217. package/dist/shacl/form-appearance.d.ts.map +1 -1
  218. package/dist/shacl/form-appearance.js +1 -1
  219. package/dist/shacl/form-appearance.js.map +1 -1
  220. package/dist/shared/graph-derived-queries.js +2 -2
  221. package/dist/shared/graph-derived-queries.js.map +1 -1
  222. package/package.json +12 -7
  223. package/src/app-subpaths.json +1 -0
  224. package/src/components/channel-icon/index.tsx +1 -1
  225. package/src/components/datastore-management/tree.ts +5 -5
  226. package/src/components/explain-fact/ExplainFact.tsx +3 -3
  227. package/src/components/planning/ActioningView.tsx +62 -70
  228. package/src/components/planning/ManualActionCard.tsx +66 -14
  229. package/src/components/planning/ManualActionList.tsx +30 -11
  230. package/src/components/planning/actioning-view-utils.ts +27 -1
  231. package/src/components/planning/plan-detail-utils.tsx +2 -0
  232. package/src/components/tool-invocation-card/ListRulesResultDisplay.tsx +2 -2
  233. package/src/components/tool-invocation-card/ToolOutputRenderer.tsx +10 -8
  234. package/src/components/tool-invocation-card/types.ts +8 -8
  235. package/src/components/tooltip/index.tsx +35 -2
  236. package/src/explain-fact/rule-presentation.ts +2 -2
  237. package/src/explain-fact/tree-model.ts +2 -2
  238. package/src/graph/entity-link.tsx +20 -0
  239. package/src/graph/graph-list-utils.ts +2 -0
  240. package/src/graph/graph-model.ts +15 -6
  241. package/src/graph/nodes/BrandAssetAnalysisView.tsx +3 -1
  242. package/src/graph/nodes/BrandFontSuggestionView.tsx +7 -1
  243. package/src/graph/nodes/BrandGuidelinesView.tsx +1 -1
  244. package/src/graph/nodes/NodePropertyTable.tsx +32 -143
  245. package/src/graph/nodes/node-property-row.tsx +154 -0
  246. package/src/graph/property-formatters.ts +5 -1
  247. package/src/graph/special-nodes/AttributeList.tsx +177 -0
  248. package/src/graph/special-nodes/EntityPreview.tsx +27 -0
  249. package/src/graph/special-nodes/EntityValueChip.tsx +85 -0
  250. package/src/graph/special-nodes/GenericView.tsx +49 -139
  251. package/src/graph/special-nodes/card-facts.ts +278 -0
  252. package/src/graph/special-nodes/property-icons.ts +59 -0
  253. package/src/graph/status-utils.ts +40 -0
  254. package/src/graph/types.ts +4 -0
  255. package/src/hooks/use-approve-anyway.ts +100 -0
  256. package/src/ldo-ui.ts +8 -0
  257. package/src/lib/find-latest-staged-rule.ts +1 -1
  258. package/src/lib/manual-actions.ts +3 -2
  259. package/src/lib/tool-icons.ts +6 -6
  260. package/src/lib/tool-names.ts +0 -1
  261. package/src/ontology/skolem.ts +2 -2
  262. package/src/providers/ActiveChatProvider.tsx +3 -1
  263. package/src/providers/ChatManagerProvider.tsx +3 -1
  264. package/src/providers/KnowledgeGraphStateProvider.tsx +1 -1
  265. package/src/providers/chat-socket-auth.ts +95 -16
  266. package/src/providers/index.tsx +16 -1
  267. package/src/routes/activity/detail/ActivityChanges.tsx +21 -5
  268. package/src/routes/activity/detail/ActivityDetail.tsx +24 -5
  269. package/src/routes/activity/detail/ActivityStepsRail.tsx +4 -2
  270. package/src/routes/activity/detail/ActivityTimeline.tsx +2 -2
  271. package/src/routes/activity/detail/NoChangesMessage.tsx +20 -0
  272. package/src/routes/data-explorer/class-properties.ts +2 -2
  273. package/src/routes/data-explorer/classes.ts +2 -2
  274. package/src/routes/data-explorer/components/RawTriples.tsx +1 -1
  275. package/src/routes/data-explorer/components/RecentTypes.tsx +1 -1
  276. package/src/routes/data-explorer/components/class-detail/Instances.tsx +1 -1
  277. package/src/routes/data-explorer/components/namespace-detail/NamespaceClassRow.tsx +1 -1
  278. package/src/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.tsx +1 -1
  279. package/src/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.tsx +1 -1
  280. package/src/routes/data-explorer/components/record-detail/ChatPreview.tsx +2 -2
  281. package/src/routes/data-explorer/recents.ts +1 -1
  282. package/src/routes/data-explorer/shapes.ts +2 -2
  283. package/src/routes/datastores/flatten.ts +1 -1
  284. package/src/routes/integrations/components/connect-forms/CanvaConnectForm.tsx +26 -0
  285. package/src/routes/integrations/components/connect-forms/DataConnectionConnectForm.tsx +38 -12
  286. package/src/routes/integrations/components/connect-forms/data-connection-fields.ts +11 -2
  287. package/src/routes/integrations/connect-forms.ts +1 -0
  288. package/src/routes/integrations/connection-view.ts +1 -0
  289. package/src/routes/integrations/types.ts +2 -0
  290. package/src/routes/plans/components/ActionPlanPage.tsx +9 -8
  291. package/src/routes/plans/components/PlanDetailRouteContent.tsx +4 -3
  292. package/src/routes/rules/hooks/useRuleFactsPreview.ts +4 -4
  293. package/src/shacl/form-appearance.ts +1 -1
  294. package/src/shared/graph-derived-queries.ts +2 -2
  295. package/dist/components/planning/ExecutionActivityRow.d.ts +0 -9
  296. package/dist/components/planning/ExecutionActivityRow.d.ts.map +0 -1
  297. package/dist/components/planning/ExecutionActivityRow.js +0 -53
  298. package/dist/components/planning/ExecutionActivityRow.js.map +0 -1
  299. package/dist/components/planning/ExecutionSectionItem.d.ts +0 -20
  300. package/dist/components/planning/ExecutionSectionItem.d.ts.map +0 -1
  301. package/dist/components/planning/ExecutionSectionItem.js +0 -66
  302. package/dist/components/planning/ExecutionSectionItem.js.map +0 -1
  303. package/dist/components/planning/ExecutionSections.d.ts +0 -16
  304. package/dist/components/planning/ExecutionSections.d.ts.map +0 -1
  305. package/dist/components/planning/ExecutionSections.js +0 -32
  306. package/dist/components/planning/ExecutionSections.js.map +0 -1
  307. package/dist/components/planning/action-plan-icons.d.ts +0 -3
  308. package/dist/components/planning/action-plan-icons.d.ts.map +0 -1
  309. package/dist/components/planning/action-plan-icons.js +0 -25
  310. package/dist/components/planning/action-plan-icons.js.map +0 -1
  311. package/dist/components/planning/execution-section-model.d.ts +0 -24
  312. package/dist/components/planning/execution-section-model.d.ts.map +0 -1
  313. package/dist/components/planning/execution-section-model.js +0 -150
  314. package/dist/components/planning/execution-section-model.js.map +0 -1
  315. package/dist/routes/data-explorer/components/TruncateTooltip.d.ts +0 -7
  316. package/dist/routes/data-explorer/components/TruncateTooltip.d.ts.map +0 -1
  317. package/dist/routes/data-explorer/components/TruncateTooltip.js +0 -9
  318. package/dist/routes/data-explorer/components/TruncateTooltip.js.map +0 -1
  319. package/src/components/planning/ExecutionActivityRow.tsx +0 -89
  320. package/src/components/planning/ExecutionSectionItem.tsx +0 -184
  321. package/src/components/planning/ExecutionSections.tsx +0 -97
  322. package/src/components/planning/action-plan-icons.tsx +0 -27
  323. package/src/components/planning/execution-section-model.ts +0 -190
  324. package/src/routes/data-explorer/components/TruncateTooltip.tsx +0 -25
@@ -1,6 +1,7 @@
1
1
  import { isPresent } from "@manta-eu/lib/present";
2
2
  import { addAll } from "@manta-eu/lib/set";
3
- import { CircleCheck, Clock, Hand, MessageSquareWarning, RotateCcw, type LucideIcon } from "lucide-react";
3
+ import { BadgeCheck, CircleCheck, Clock, Hand, MessageSquareWarning, RotateCcw, type LucideIcon } from "lucide-react";
4
+ import { Fragment } from "react";
4
5
  import { match } from "ts-pattern";
5
6
  import { Badge, type BadgeVariant } from "#components/badge/index";
6
7
  import { Button } from "#components/button/index";
@@ -30,10 +31,25 @@ export type ManualActionCardProps = {
30
31
  onResolve: (resolution: ManualActionResolution) => void;
31
32
  canResolve?: boolean;
32
33
  disabledReason?: string;
34
+ /** Offered when the action is about something a person can approve despite the checks, such as a creative. */
35
+ onApproveAnyway?: () => void;
36
+ approvingAnyway?: boolean;
37
+ approvedAnyway?: boolean;
33
38
  };
34
39
 
35
40
  export function ManualActionCard(props: ManualActionCardProps) {
36
- const { manualAction, entities = [], description, resolving, onResolve, canResolve = true, disabledReason } = props;
41
+ const {
42
+ manualAction,
43
+ entities = [],
44
+ description,
45
+ resolving,
46
+ onResolve,
47
+ canResolve = true,
48
+ disabledReason,
49
+ onApproveAnyway,
50
+ approvingAnyway = false,
51
+ approvedAnyway = false,
52
+ } = props;
37
53
 
38
54
  const instruction = description ?? manualAction.description ?? null;
39
55
  const title = manualAction.label ?? instruction ?? buildManualActionTitle(manualAction);
@@ -67,6 +83,9 @@ export function ManualActionCard(props: ManualActionCardProps) {
67
83
  onResolve={onResolve}
68
84
  canResolve={canResolve}
69
85
  disabledReason={disabledReason}
86
+ onApproveAnyway={onApproveAnyway}
87
+ approvingAnyway={approvingAnyway}
88
+ approvedAnyway={approvedAnyway}
70
89
  />
71
90
  )}
72
91
 
@@ -274,28 +293,61 @@ type CardFooterProps = {
274
293
  onResolve: (resolution: ManualActionResolution) => void;
275
294
  canResolve: boolean;
276
295
  disabledReason?: string;
296
+ onApproveAnyway?: () => void;
297
+ approvingAnyway: boolean;
298
+ approvedAnyway: boolean;
277
299
  };
278
300
 
279
301
  function CardFooter(props: CardFooterProps) {
280
- const { isResolving, resolvingChoice, retryable, defaultResolution, onResolve, canResolve, disabledReason } = props;
302
+ const {
303
+ isResolving,
304
+ resolvingChoice,
305
+ retryable,
306
+ defaultResolution,
307
+ onResolve,
308
+ canResolve,
309
+ disabledReason,
310
+ onApproveAnyway,
311
+ approvingAnyway,
312
+ approvedAnyway,
313
+ } = props;
281
314
  const choices = resolutionChoices(retryable, defaultResolution);
315
+ const busy = isResolving || approvingAnyway || approvedAnyway;
282
316
 
283
317
  return (
284
318
  <div className="flex items-center bg-muted px-3 py-3">
285
319
  <DisabledActionTooltip reason={canResolve ? undefined : disabledReason}>
286
320
  <div className="flex flex-wrap items-center gap-2">
287
321
  {choices.map((choice, index) => (
288
- <Button
289
- key={choice}
290
- size="sm"
291
- rounded="lg"
292
- variant={index === 0 ? "primary" : "tertiary"}
293
- icon={choiceIcons[choice]}
294
- label={choiceLabels[choice]}
295
- disabled={!canResolve || isResolving}
296
- isLoading={isResolving && resolvingChoice === choice}
297
- onClick={() => onResolve(choice)}
298
- />
322
+ <Fragment key={choice}>
323
+ {choice === "REJECTED" && approvedAnyway && (
324
+ <span className="typography-tiny text-muted-foreground">
325
+ Approved. This review closes when the plan next runs.
326
+ </span>
327
+ )}
328
+ {choice === "REJECTED" && onApproveAnyway && !approvedAnyway && (
329
+ <Button
330
+ size="sm"
331
+ rounded="lg"
332
+ variant="secondary"
333
+ icon={BadgeCheck}
334
+ label="Approve anyway"
335
+ disabled={!canResolve || busy}
336
+ isLoading={approvingAnyway}
337
+ onClick={onApproveAnyway}
338
+ />
339
+ )}
340
+ <Button
341
+ size="sm"
342
+ rounded="lg"
343
+ variant={index === 0 ? "primary" : "tertiary"}
344
+ icon={choiceIcons[choice]}
345
+ label={choiceLabels[choice]}
346
+ disabled={!canResolve || busy}
347
+ isLoading={isResolving && resolvingChoice === choice}
348
+ onClick={() => onResolve(choice)}
349
+ />
350
+ </Fragment>
299
351
  ))}
300
352
  </div>
301
353
  </DisabledActionTooltip>
@@ -8,6 +8,7 @@ import {
8
8
  type ManualActionResolution,
9
9
  type ManualActionResolving,
10
10
  } from "#hooks/use-manual-actions";
11
+ import { approvalReviewKey } from "#lib/manual-actions";
11
12
 
12
13
  export type ManualActionListViewProps = {
13
14
  actions: ManualAction[];
@@ -19,6 +20,10 @@ export type ManualActionListViewProps = {
19
20
  isLoading?: boolean;
20
21
  failed?: boolean;
21
22
  emptyFallback?: ReactNode;
23
+ approvableAnalyses?: Map<string, string>;
24
+ onApproveAnyway?: (analysisIri: string, reviewKey: string) => void;
25
+ approvingAnyway?: ReadonlySet<string>;
26
+ approvedAnyway?: ReadonlySet<string>;
22
27
  };
23
28
 
24
29
  const skeletonShapes = [
@@ -38,6 +43,10 @@ export function ManualActionListView(props: ManualActionListViewProps) {
38
43
  isLoading = false,
39
44
  failed = false,
40
45
  emptyFallback,
46
+ approvableAnalyses,
47
+ onApproveAnyway,
48
+ approvingAnyway,
49
+ approvedAnyway,
41
50
  } = props;
42
51
 
43
52
  if (isLoading) {
@@ -75,17 +84,27 @@ export function ManualActionListView(props: ManualActionListViewProps) {
75
84
 
76
85
  return (
77
86
  <div className="flex flex-col">
78
- {actions.map((action) => (
79
- <ManualActionCard
80
- key={action.subjectIri}
81
- manualAction={action}
82
- entities={targetsBySubject?.get(action.subjectIri) ?? []}
83
- resolving={resolving}
84
- onResolve={(resolution) => onResolve(action, resolution)}
85
- canResolve={canResolve}
86
- disabledReason={disabledReason}
87
- />
88
- ))}
87
+ {actions.map((action) => {
88
+ const analysisIri = approvableAnalyses?.get(action.subjectIri);
89
+ return (
90
+ <ManualActionCard
91
+ key={action.subjectIri}
92
+ manualAction={action}
93
+ entities={targetsBySubject?.get(action.subjectIri) ?? []}
94
+ resolving={resolving}
95
+ onResolve={(resolution) => onResolve(action, resolution)}
96
+ canResolve={canResolve}
97
+ disabledReason={disabledReason}
98
+ onApproveAnyway={
99
+ isPresent(analysisIri) && onApproveAnyway
100
+ ? () => onApproveAnyway(analysisIri, approvalReviewKey(action))
101
+ : undefined
102
+ }
103
+ approvingAnyway={isPresent(analysisIri) && (approvingAnyway?.has(analysisIri) ?? false)}
104
+ approvedAnyway={approvedAnyway?.has(approvalReviewKey(action)) ?? false}
105
+ />
106
+ );
107
+ })}
89
108
  </div>
90
109
  );
91
110
  }
@@ -1,9 +1,35 @@
1
1
  import { GQLActionPlanState } from "@manta-eu/client";
2
+ import { isPresent } from "@manta-eu/lib/present";
2
3
  import { match } from "ts-pattern";
3
- import { parseTimestampMs } from "./execution-section-model";
4
+
5
+ export function parseTimestampMs(timestamp: string | null | undefined): number | null {
6
+ if (!timestamp) return null;
7
+ const value = new Date(timestamp).getTime();
8
+ return Number.isFinite(value) ? value : null;
9
+ }
4
10
 
5
11
  export type ExecutionStatus = "idle" | "running" | "completed" | "failed" | "needs-approval";
6
12
 
13
+ export type RunSurface = "completed-changes" | "run" | "starting-run" | "loading" | "none";
14
+
15
+ export type DeriveRunSurfaceArgs = {
16
+ executionStatus: ExecutionStatus;
17
+ runIri: string | null;
18
+ hasCompletedChangesSlot: boolean;
19
+ isLoading: boolean;
20
+ };
21
+
22
+ export function deriveRunSurface(args: DeriveRunSurfaceArgs): RunSurface {
23
+ const { executionStatus, runIri, hasCompletedChangesSlot, isLoading } = args;
24
+
25
+ if (executionStatus === "completed" && hasCompletedChangesSlot) return "completed-changes";
26
+ if (isPresent(runIri)) return "run";
27
+ if (executionStatus === "running" || executionStatus === "needs-approval") return "starting-run";
28
+ if (isLoading) return "loading";
29
+
30
+ return "none";
31
+ }
32
+
7
33
  export type DeriveExecutionStatusArgs = {
8
34
  provenance: {
9
35
  planErrorMessage: string | null;
@@ -108,6 +108,7 @@ export function formatIntegration(integration: GQLIntegration | null): string {
108
108
  .with(GQLIntegration.Slack, () => "Slack")
109
109
  .with(GQLIntegration.Figma, () => "Figma")
110
110
  .with(GQLIntegration.Dash, () => "Dash")
111
+ .with(GQLIntegration.Canva, () => "Canva")
111
112
  .exhaustive();
112
113
  }
113
114
 
@@ -123,6 +124,7 @@ export function integrationToChannel(integration: GQLIntegration): Channel | nul
123
124
  [GQLIntegration.Slack]: null,
124
125
  [GQLIntegration.Figma]: null,
125
126
  [GQLIntegration.Dash]: null,
127
+ [GQLIntegration.Canva]: null,
126
128
  } as const satisfies Record<GQLIntegration, Channel | null>;
127
129
 
128
130
  return integrationChannelMap[integration];
@@ -1,7 +1,7 @@
1
- import type { GetRDFoxRulesToolResult } from "./types";
1
+ import type { GetRulesToolResult } from "./types";
2
2
 
3
3
  type ListRulesResultDisplayProps = {
4
- result: GetRDFoxRulesToolResult;
4
+ result: GetRulesToolResult;
5
5
  };
6
6
 
7
7
  export function ListRulesResultDisplay(_props: ListRulesResultDisplayProps) {
@@ -1,3 +1,4 @@
1
+ import { withDatastoreQueryParam } from "@manta-eu/client/shared/datastore-path";
1
2
  import { isShowEntitiesResult } from "@manta-eu/client/shared/tools";
2
3
  import {
3
4
  isWorkspaceArtifactInlineMediaType,
@@ -17,7 +18,7 @@ import type {
17
18
  ChartToolResult,
18
19
  ErrorToolResult,
19
20
  ExplainFactToolResult,
20
- GetRDFoxRulesToolResult,
21
+ GetRulesToolResult,
21
22
  ManageRulesResult,
22
23
  ShowcaseToolResult,
23
24
  ShowEntitiesToolResult,
@@ -26,8 +27,8 @@ import type {
26
27
  import {
27
28
  isChartToolResult,
28
29
  isErrorToolResult,
29
- isExplainRDFoxRulesResult,
30
- isGetRDFoxRulesToolResult,
30
+ isExplainFactToolResult,
31
+ isGetRulesToolResult,
31
32
  isManageRulesResult,
32
33
  isShowcaseToolResult,
33
34
  isWorkspaceArtifactResult,
@@ -45,6 +46,7 @@ import {
45
46
  import { decodeChartEntities } from "#lib/decode-chart-entities";
46
47
  import { cn } from "#lib/utils";
47
48
  import { useChatManagerConnection } from "#providers/ChatManagerProvider";
49
+ import { useMantaClient } from "#providers/MantaClientProvider";
48
50
 
49
51
  type ErrorResultDisplayProps = {
50
52
  result: ErrorToolResult;
@@ -126,11 +128,13 @@ type WorkspaceArtifactResultDisplayProps = {
126
128
  function WorkspaceArtifactResultDisplay(props: WorkspaceArtifactResultDisplayProps) {
127
129
  const { result } = props;
128
130
 
131
+ const { datastoreId } = useMantaClient();
132
+
129
133
  return (
130
134
  <FileMessagePart
131
135
  part={{
132
136
  type: "file",
133
- url: result.url,
137
+ url: withDatastoreQueryParam(result.url, datastoreId),
134
138
  mediaType: result.mediaType,
135
139
  filename: result.filename,
136
140
  }}
@@ -151,10 +155,8 @@ export function ToolOutputRenderer(props: ToolOutputRendererProps) {
151
155
  .when(isErrorToolResult, (errorResult: ErrorToolResult) => <ErrorResultDisplay result={errorResult} />)
152
156
  .when(isChartToolResult, (chartResult: ChartToolResult) => <ChartResultDisplay result={chartResult} />)
153
157
  .when(isManageRulesResult, (rulesResult: ManageRulesResult) => <ManageRulesResultDisplay result={rulesResult} />)
154
- .when(isGetRDFoxRulesToolResult, (rulesResult: GetRDFoxRulesToolResult) => (
155
- <ListRulesResultDisplay result={rulesResult} />
156
- ))
157
- .when(isExplainRDFoxRulesResult, (explainResult: ExplainFactToolResult) => (
158
+ .when(isGetRulesToolResult, (rulesResult: GetRulesToolResult) => <ListRulesResultDisplay result={rulesResult} />)
159
+ .when(isExplainFactToolResult, (explainResult: ExplainFactToolResult) => (
158
160
  <ExplainFactResultDisplay result={explainResult} toolUIPart={toolUIPart} />
159
161
  ))
160
162
  .when(isShowcaseToolResult, (showcaseResult: ShowcaseToolResult) => (
@@ -3,7 +3,7 @@ import {
3
3
  type ActionPlanShowcaseOutput,
4
4
  type ShowEntitiesOutput,
5
5
  } from "@manta-eu/client/shared/tools";
6
- import type { GetRDFoxRulesOutputSuccess } from "@manta-eu/client/shared/tools/types";
6
+ import type { GetRulesOutputSuccess } from "@manta-eu/client/shared/tools/types";
7
7
  import { workspaceArtifactSchema, type WorkspaceArtifact } from "@manta-eu/client/shared/workspace-artifacts";
8
8
  import { isJsonLdDocument } from "@manta-eu/client/types/jsonld";
9
9
  import type { DatalogRule, InferenceVerificationResult } from "@manta-eu/datalog-parser";
@@ -45,7 +45,7 @@ export type StagedManageRulesResult = ManageRulesResult & {
45
45
 
46
46
  export type ShowcaseToolResult = Extract<ActionPlanShowcaseOutput, { planIri: string }>;
47
47
  export type ShowEntitiesToolResult = Extract<ShowEntitiesOutput, { entityIris: string[] }>;
48
- export type GetRDFoxRulesToolResult = GetRDFoxRulesOutputSuccess;
48
+ export type GetRulesToolResult = GetRulesOutputSuccess;
49
49
  export type ExplainFactToolResult = ExplainFactOutput;
50
50
 
51
51
  export type ToolResult =
@@ -54,7 +54,7 @@ export type ToolResult =
54
54
  | ManageRulesResult
55
55
  | ShowcaseToolResult
56
56
  | ShowEntitiesToolResult
57
- | GetRDFoxRulesToolResult
57
+ | GetRulesToolResult
58
58
  | ExplainFactToolResult
59
59
  | WorkspaceArtifact
60
60
  | { content: Array<{ type: string; text: string }> }
@@ -95,11 +95,11 @@ export function isShowcaseToolResult(result: unknown): result is ShowcaseToolRes
95
95
  return isObjectWithProps(result, ["planIri"]);
96
96
  }
97
97
 
98
- export function isGetRDFoxRulesToolResult(result: unknown): result is GetRDFoxRulesOutputSuccess {
98
+ export function isGetRulesToolResult(result: unknown): result is GetRulesOutputSuccess {
99
99
  return isObjectWithProps(result, ["rules"]) && Array.isArray(result.rules);
100
100
  }
101
101
 
102
- export function isExplainRDFoxRulesResult(result: unknown): result is ExplainFactToolResult {
102
+ export function isExplainFactToolResult(result: unknown): result is ExplainFactToolResult {
103
103
  if (typeof result !== "object" || result === null || Array.isArray(result)) return false;
104
104
  if ("is_error" in result || "rules" in result || "type" in result) return false;
105
105
 
@@ -120,8 +120,8 @@ export function hasVisualOutput(output: unknown): boolean {
120
120
  isManageRulesResult(output) ||
121
121
  isShowcaseToolResult(output) ||
122
122
  isShowEntitiesResult(output) ||
123
- isGetRDFoxRulesToolResult(output) ||
124
- isExplainRDFoxRulesResult(output) ||
123
+ isGetRulesToolResult(output) ||
124
+ isExplainFactToolResult(output) ||
125
125
  isWorkspaceArtifactResult(output))
126
126
  );
127
127
  }
@@ -129,7 +129,7 @@ export function hasVisualOutput(output: unknown): boolean {
129
129
  export function hasInlineVisualOutput(output: unknown): boolean {
130
130
  return (
131
131
  isChartToolResult(output) ||
132
- isExplainRDFoxRulesResult(output) ||
132
+ isExplainFactToolResult(output) ||
133
133
  isShowEntitiesResult(output) ||
134
134
  isWorkspaceArtifactResult(output)
135
135
  );
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
4
- import type { ComponentPropsWithoutRef, ElementRef } from "react";
5
- import { forwardRef } from "react";
4
+ import type { ComponentPropsWithoutRef, ElementRef, ReactNode } from "react";
5
+ import { forwardRef, useState } from "react";
6
6
  import { cn } from "#style";
7
7
 
8
8
  export const TooltipProvider = TooltipPrimitive.Provider;
@@ -43,3 +43,36 @@ export const TooltipContent = forwardRef<ElementRef<typeof TooltipPrimitive.Cont
43
43
  ),
44
44
  );
45
45
  TooltipContent.displayName = "TooltipContent";
46
+
47
+ export type TruncateTooltipProps = { text: string; className: string; children?: ReactNode };
48
+
49
+ export function TruncateTooltip(props: TruncateTooltipProps) {
50
+ const { text, className, children } = props;
51
+
52
+ const [isTruncated, setIsTruncated] = useState(false);
53
+
54
+ return (
55
+ <Tooltip>
56
+ <TooltipTrigger asChild>
57
+ <span
58
+ className={className}
59
+ onMouseEnter={(event) => {
60
+ const element = event.currentTarget;
61
+ // Line height can round a single line 1px taller than its box, so only a real clamp counts.
62
+ setIsTruncated(
63
+ element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight + 1,
64
+ );
65
+ }}
66
+ >
67
+ {children ?? text}
68
+ </span>
69
+ </TooltipTrigger>
70
+
71
+ {isTruncated && (
72
+ <TooltipContent showArrow={false} className="max-h-64 max-w-sm overflow-y-auto break-words text-left">
73
+ <p className="typography-tiny">{text}</p>
74
+ </TooltipContent>
75
+ )}
76
+ </Tooltip>
77
+ );
78
+ }
@@ -362,7 +362,7 @@ function ruleNameTermFromHeadText(headText: string): string {
362
362
  return predicate.trim();
363
363
  }
364
364
 
365
- // Explain payloads echo RDFox-serialized rules (bare ON, atom-free aggregates),
365
+ // Explain payloads echo rules as the datastore serializes them (bare ON, atom-free aggregates),
366
366
  // so authored text falls through to the expanded grammar when the strict parse fails.
367
367
  function explainRuleAst(rule: string): DatalogRule | undefined {
368
368
  return parseDatalogRuleCached(rule).ast ?? parseGroundedDatalogRuleCached(rule).ast ?? undefined;
@@ -415,7 +415,7 @@ function collectFormulaBindings(
415
415
  .with({ type: "aggregate" }, (aggregate) => {
416
416
  if (groundedFormula?.type !== "aggregate") return;
417
417
 
418
- // AS targets first, then the aggregate's inner atoms — RDFox grounds those too
418
+ // AS targets first, then the aggregate's inner atoms — the datastore grounds those too
419
419
  // (e.g. `:clicks[?c, ?x]` → `:clicks[:C_1, 10]`), and first-wins keeps a head binding.
420
420
  if (groundedFormula.bindings?.length === aggregate.bindings?.length) {
421
421
  aggregate.bindings?.forEach((binding, index) => {
@@ -380,7 +380,7 @@ function flattenFacts(output: ExplainFactOutput): FactEntry[] {
380
380
  const values = Array.isArray(value) ? value : [value];
381
381
 
382
382
  return values.flatMap((fact, index) => {
383
- if (!isRDFoxFact(fact)) return [];
383
+ if (!isExplainedFact(fact)) return [];
384
384
 
385
385
  return [
386
386
  {
@@ -393,7 +393,7 @@ function flattenFacts(output: ExplainFactOutput): FactEntry[] {
393
393
  });
394
394
  }
395
395
 
396
- function isRDFoxFact(value: unknown): value is ExplainedFact {
396
+ function isExplainedFact(value: unknown): value is ExplainedFact {
397
397
  return typeof value === "object" && value !== null && !Array.isArray(value);
398
398
  }
399
399
 
@@ -0,0 +1,20 @@
1
+ import { type ComponentType, createContext, type ReactNode, useContext } from "react";
2
+
3
+ export type EntityLinkProps = { iri: string; className?: string; children: ReactNode };
4
+
5
+ export type EntityLinkComponent = ComponentType<EntityLinkProps>;
6
+
7
+ // The host app supplies how an entity opens (its router and record route); without one, entities render unlinked.
8
+ const EntityLinkContext = createContext<EntityLinkComponent | undefined>(undefined);
9
+
10
+ export type EntityLinkProviderProps = { component: EntityLinkComponent; children: ReactNode };
11
+
12
+ export function EntityLinkProvider(props: EntityLinkProviderProps) {
13
+ const { component, children } = props;
14
+
15
+ return <EntityLinkContext.Provider value={component}>{children}</EntityLinkContext.Provider>;
16
+ }
17
+
18
+ export function useEntityLink(): EntityLinkComponent | undefined {
19
+ return useContext(EntityLinkContext);
20
+ }
@@ -87,6 +87,7 @@ export type NodePropertyChange = {
87
87
 
88
88
  export type NodePropertyPreview = {
89
89
  id: string;
90
+ predicate?: string;
90
91
  label: string;
91
92
  value: string;
92
93
  changeType?: PropertyChangeType;
@@ -162,6 +163,7 @@ export function selectPriorityPreviewFields(
162
163
 
163
164
  return {
164
165
  id: `${property.key}-${index}`,
166
+ predicate: property.iri,
165
167
  label: property.label ?? propertyLabelFromKey(property.key),
166
168
  value,
167
169
  rawValue: String(property.value),
@@ -1,3 +1,4 @@
1
+ import { isFullIri } from "@manta-eu/client/shared/rdf-namespaces";
1
2
  import { labelPredicateSuffixes } from "@manta-eu/rdf-lib/detail-view-types";
2
3
  import { expandPrefix, wellKnownPredicates } from "@manta-eu/rdf-lib/namespaces";
3
4
  import type { RdfGraph } from "../lib/rdf-helpers";
@@ -10,7 +11,7 @@ import {
10
11
  import { humanizePredicateName, type NodesAndEdges, type RDFEdge, shortenUri } from "./graph-utils";
11
12
  import { readVocabValue } from "./nodes/typed-node-helpers";
12
13
  import { mantaLightTheme } from "./themes";
13
- import type { LayoutDirection, NodeProperty, RDFNode } from "./types";
14
+ import type { LayoutDirection, NodeProperty, NodeRelation, RDFNode } from "./types";
14
15
 
15
16
  const labelPredicate = wellKnownPredicates.label;
16
17
  const rdfType = wellKnownPredicates.type;
@@ -44,6 +45,7 @@ type NodeAccumulator = {
44
45
  label?: string;
45
46
  type?: string;
46
47
  data: Record<string, unknown>;
48
+ relations: NodeRelation[];
47
49
  };
48
50
 
49
51
  type GraphEdgeRecord = {
@@ -60,7 +62,7 @@ function createOrGetNodeAccumulator(
60
62
  ): NodeAccumulator {
61
63
  let node = nodeData.get(subjectId);
62
64
  if (!node) {
63
- node = { data: {} };
65
+ node = { data: {}, relations: [] };
64
66
  nodeData.set(subjectId, node);
65
67
  connectionCounts.set(subjectId, 0);
66
68
  }
@@ -159,7 +161,7 @@ function buildNodesAndEdges(
159
161
  const allNodeIds = new Set(nodeData.keys());
160
162
  const hubThreshold = computeHubThreshold(connectionCounts);
161
163
 
162
- const graphNodes: RDFNode[] = Array.from(nodeData).map(([id, { label, type, data }]) => {
164
+ const graphNodes: RDFNode[] = Array.from(nodeData).map(([id, { label, type, data, relations }]) => {
163
165
  const childIds = (parentChildMap.get(id) || []).filter((childId) => allNodeIds.has(childId));
164
166
  const parentId = childParentMap.get(id);
165
167
  const depth = nodeDepths.get(id) || 0;
@@ -193,6 +195,7 @@ function buildNodesAndEdges(
193
195
  isHub: connCount >= hubThreshold,
194
196
  jsonLd: { "@id": id, "@type": type, ...data },
195
197
  properties,
198
+ relations,
196
199
  childIds,
197
200
  parentId,
198
201
  isCollapsed: false,
@@ -334,11 +337,15 @@ export function rdfGraphToNodesAndEdges(
334
337
  const longNumericPattern = /\d{10,}/;
335
338
  const leafValueSchemes = ["http://", "https://", "s3://"];
336
339
 
340
+ // A stored file or web address is a value to render, not a neighbor (without `s3:`, a long digit run reads as a ref).
341
+ function isLeafValue(targetId: string): boolean {
342
+ const isNamespacedIri = targetId.includes("#") || targetId.includes("vocab");
343
+ return !isNamespacedIri && leafValueSchemes.some((scheme) => targetId.startsWith(scheme));
344
+ }
345
+
337
346
  function isEnumLikeRef(targetId: string): boolean {
338
347
  if (definedSubjects.has(targetId)) return false;
339
- const isNamespacedIri = targetId.includes("#") || targetId.includes("vocab");
340
- // A stored file is a value to render, not a neighbor: without `s3:` a key with a long digit run reads as a ref.
341
- if (!isNamespacedIri && leafValueSchemes.some((scheme) => targetId.startsWith(scheme))) return true;
348
+ if (isLeafValue(targetId)) return true;
342
349
  const localName = targetId.split(/[#/]/).pop() ?? targetId;
343
350
  if (uuidPattern.test(localName) || longNumericPattern.test(localName)) return false;
344
351
  return true;
@@ -379,10 +386,12 @@ export function rdfGraphToNodesAndEdges(
379
386
 
380
387
  if (isEnumLikeRef(targetId)) {
381
388
  mergeNodeValue(node.data, predicate, targetId);
389
+ if (!isLeafValue(targetId) && isFullIri(targetId)) node.relations.push({ predicate, target: targetId });
382
390
  continue;
383
391
  }
384
392
 
385
393
  createOrGetNodeAccumulator(nodeData, connectionCounts, targetId);
394
+ if (isFullIri(targetId)) node.relations.push({ predicate, target: targetId });
386
395
  connectionCounts.set(subjectId, (connectionCounts.get(subjectId) || 0) + 1);
387
396
  connectionCounts.set(targetId, (connectionCounts.get(targetId) || 0) + 1);
388
397
 
@@ -13,6 +13,7 @@ import { useRedirectEndpoint } from "#hooks/use-redirect-endpoint";
13
13
  const filePredicate = `${namespaces.brand}file`;
14
14
  const mimePredicate = `${namespaces.nmo}contentMimeType`;
15
15
  const descriptionPredicate = `${namespaces.brand}assetDescription`;
16
+ const listedElsewhere = [filePredicate, mimePredicate, descriptionPredicate];
16
17
 
17
18
  // The generated schema requires `m:file`, which only the planned request carries, so a lens read never matches.
18
19
  export const BrandAssetAnalysisView = memo(function BrandAssetAnalysisView(props: EntityViewProps) {
@@ -46,8 +47,9 @@ export const BrandAssetAnalysisView = memo(function BrandAssetAnalysisView(props
46
47
 
47
48
  <NodePropertyTable
48
49
  properties={data.properties}
50
+ relations={data.relations}
49
51
  jsonLd={data.jsonLd}
50
- omitPredicates={[filePredicate, mimePredicate, descriptionPredicate]}
52
+ omitPredicates={listedElsewhere}
51
53
  />
52
54
  </BrandNodeBody>
53
55
  </EntityCardShell>
@@ -23,6 +23,7 @@ import { useFontFace } from "#hooks/use-font-face";
23
23
  import { useRedirectEndpoint } from "#hooks/use-redirect-endpoint";
24
24
 
25
25
  const weightPredicate = `${namespaces.brand}hasSuggestedWeight`;
26
+ const listedElsewhere = [weightPredicate];
26
27
  const specimenText = "Aa Bb Cc Qq Rr 0123456789 — The quick brown fox jumps over the lazy dog";
27
28
 
28
29
  function useSuggestedWeights(iris: string[]): SuggestedWeight[] {
@@ -118,7 +119,12 @@ export const BrandFontSuggestionView = memo(function BrandFontSuggestionView(pro
118
119
  </ul>
119
120
  )}
120
121
 
121
- <NodePropertyTable properties={data.properties} jsonLd={data.jsonLd} omitPredicates={[weightPredicate]} />
122
+ <NodePropertyTable
123
+ properties={data.properties}
124
+ jsonLd={data.jsonLd}
125
+ relations={data.relations}
126
+ omitPredicates={listedElsewhere}
127
+ />
122
128
  </BrandNodeBody>
123
129
  </EntityCardShell>
124
130
  );
@@ -18,7 +18,7 @@ export const BrandGuidelinesView = memo(function BrandGuidelinesView(props: Enti
18
18
  onContextMenu={onContextMenu}
19
19
  >
20
20
  <BrandNodeBody>
21
- <NodePropertyTable properties={data.properties} jsonLd={data.jsonLd} />
21
+ <NodePropertyTable properties={data.properties} jsonLd={data.jsonLd} relations={data.relations} />
22
22
  </BrandNodeBody>
23
23
  </EntityCardShell>
24
24
  );