@manta-eu/react 0.1.10 → 0.2.1

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/chat-view/ChatTurnErrorNotice.d.ts.map +1 -1
  6. package/dist/components/chat-view/ChatTurnErrorNotice.js +3 -1
  7. package/dist/components/chat-view/ChatTurnErrorNotice.js.map +1 -1
  8. package/dist/components/layouts/ConnectedCustomApp.d.ts +13 -0
  9. package/dist/components/layouts/ConnectedCustomApp.d.ts.map +1 -0
  10. package/dist/components/layouts/ConnectedCustomApp.js +37 -0
  11. package/dist/components/layouts/ConnectedCustomApp.js.map +1 -0
  12. package/dist/components/layouts/Sidebar.d.ts.map +1 -1
  13. package/dist/components/layouts/Sidebar.js +6 -3
  14. package/dist/components/layouts/Sidebar.js.map +1 -1
  15. package/dist/components/planning/ActioningView.d.ts +1 -2
  16. package/dist/components/planning/ActioningView.d.ts.map +1 -1
  17. package/dist/components/planning/ActioningView.js +19 -44
  18. package/dist/components/planning/ActioningView.js.map +1 -1
  19. package/dist/components/planning/ManualActionCard.d.ts +4 -0
  20. package/dist/components/planning/ManualActionCard.d.ts.map +1 -1
  21. package/dist/components/planning/ManualActionCard.js +7 -5
  22. package/dist/components/planning/ManualActionCard.js.map +1 -1
  23. package/dist/components/planning/ManualActionList.d.ts +4 -0
  24. package/dist/components/planning/ManualActionList.d.ts.map +1 -1
  25. package/dist/components/planning/ManualActionList.js +8 -2
  26. package/dist/components/planning/ManualActionList.js.map +1 -1
  27. package/dist/components/planning/actioning-view-utils.d.ts +9 -0
  28. package/dist/components/planning/actioning-view-utils.d.ts.map +1 -1
  29. package/dist/components/planning/actioning-view-utils.js +19 -1
  30. package/dist/components/planning/actioning-view-utils.js.map +1 -1
  31. package/dist/components/table-skeleton/index.d.ts +2 -0
  32. package/dist/components/table-skeleton/index.d.ts.map +1 -1
  33. package/dist/components/table-skeleton/index.js +2 -1
  34. package/dist/components/table-skeleton/index.js.map +1 -1
  35. package/dist/components/tooltip/index.d.ts +7 -0
  36. package/dist/components/tooltip/index.d.ts.map +1 -1
  37. package/dist/components/tooltip/index.js +10 -1
  38. package/dist/components/tooltip/index.js.map +1 -1
  39. package/dist/globals.css +19 -6
  40. package/dist/graph/createNodeRouter.js +3 -3
  41. package/dist/graph/createNodeRouter.js.map +1 -1
  42. package/dist/graph/entity-link.d.ts +14 -0
  43. package/dist/graph/entity-link.d.ts.map +1 -0
  44. package/dist/graph/entity-link.js +12 -0
  45. package/dist/graph/entity-link.js.map +1 -0
  46. package/dist/graph/graph-list-utils.d.ts +1 -0
  47. package/dist/graph/graph-list-utils.d.ts.map +1 -1
  48. package/dist/graph/graph-list-utils.js +1 -0
  49. package/dist/graph/graph-list-utils.js.map +1 -1
  50. package/dist/graph/graph-model.d.ts.map +1 -1
  51. package/dist/graph/graph-model.js +14 -5
  52. package/dist/graph/graph-model.js.map +1 -1
  53. package/dist/graph/nodes/BrandAssetAnalysisView.d.ts.map +1 -1
  54. package/dist/graph/nodes/BrandAssetAnalysisView.js +2 -1
  55. package/dist/graph/nodes/BrandAssetAnalysisView.js.map +1 -1
  56. package/dist/graph/nodes/BrandFontSuggestionView.d.ts +3 -0
  57. package/dist/graph/nodes/BrandFontSuggestionView.d.ts.map +1 -0
  58. package/dist/graph/nodes/{BrandFontFamilyView.js → BrandFontSuggestionView.js} +22 -13
  59. package/dist/graph/nodes/BrandFontSuggestionView.js.map +1 -0
  60. package/dist/graph/nodes/BrandGuidelinesView.js +1 -1
  61. package/dist/graph/nodes/BrandGuidelinesView.js.map +1 -1
  62. package/dist/graph/nodes/NodePropertyTable.d.ts +4 -2
  63. package/dist/graph/nodes/NodePropertyTable.d.ts.map +1 -1
  64. package/dist/graph/nodes/NodePropertyTable.js +12 -59
  65. package/dist/graph/nodes/NodePropertyTable.js.map +1 -1
  66. package/dist/graph/nodes/brand-font.d.ts +8 -0
  67. package/dist/graph/nodes/brand-font.d.ts.map +1 -1
  68. package/dist/graph/nodes/brand-font.js +6 -0
  69. package/dist/graph/nodes/brand-font.js.map +1 -1
  70. package/dist/graph/nodes/brand-shared.d.ts +0 -3
  71. package/dist/graph/nodes/brand-shared.d.ts.map +1 -1
  72. package/dist/graph/nodes/brand-shared.js +1 -4
  73. package/dist/graph/nodes/brand-shared.js.map +1 -1
  74. package/dist/graph/nodes/node-property-row.d.ts +30 -0
  75. package/dist/graph/nodes/node-property-row.d.ts.map +1 -0
  76. package/dist/graph/nodes/node-property-row.js +35 -0
  77. package/dist/graph/nodes/node-property-row.js.map +1 -0
  78. package/dist/graph/property-formatters.d.ts +1 -0
  79. package/dist/graph/property-formatters.d.ts.map +1 -1
  80. package/dist/graph/property-formatters.js +4 -1
  81. package/dist/graph/property-formatters.js.map +1 -1
  82. package/dist/graph/special-nodes/AttributeList.d.ts +27 -0
  83. package/dist/graph/special-nodes/AttributeList.d.ts.map +1 -0
  84. package/dist/graph/special-nodes/AttributeList.js +57 -0
  85. package/dist/graph/special-nodes/AttributeList.js.map +1 -0
  86. package/dist/graph/special-nodes/EntityPreview.d.ts +5 -0
  87. package/dist/graph/special-nodes/EntityPreview.d.ts.map +1 -0
  88. package/dist/graph/special-nodes/EntityPreview.js +19 -0
  89. package/dist/graph/special-nodes/EntityPreview.js.map +1 -0
  90. package/dist/graph/special-nodes/EntityValueChip.d.ts +11 -0
  91. package/dist/graph/special-nodes/EntityValueChip.d.ts.map +1 -0
  92. package/dist/graph/special-nodes/EntityValueChip.js +40 -0
  93. package/dist/graph/special-nodes/EntityValueChip.js.map +1 -0
  94. package/dist/graph/special-nodes/GenericView.d.ts +2 -1
  95. package/dist/graph/special-nodes/GenericView.d.ts.map +1 -1
  96. package/dist/graph/special-nodes/GenericView.js +23 -69
  97. package/dist/graph/special-nodes/GenericView.js.map +1 -1
  98. package/dist/graph/special-nodes/card-facts.d.ts +52 -0
  99. package/dist/graph/special-nodes/card-facts.d.ts.map +1 -0
  100. package/dist/graph/special-nodes/card-facts.js +189 -0
  101. package/dist/graph/special-nodes/card-facts.js.map +1 -0
  102. package/dist/graph/special-nodes/property-icons.d.ts +9 -0
  103. package/dist/graph/special-nodes/property-icons.d.ts.map +1 -0
  104. package/dist/graph/special-nodes/property-icons.js +39 -0
  105. package/dist/graph/special-nodes/property-icons.js.map +1 -0
  106. package/dist/graph/status-utils.d.ts +16 -0
  107. package/dist/graph/status-utils.d.ts.map +1 -1
  108. package/dist/graph/status-utils.js +35 -0
  109. package/dist/graph/status-utils.js.map +1 -1
  110. package/dist/graph/types.d.ts +5 -0
  111. package/dist/graph/types.d.ts.map +1 -1
  112. package/dist/hooks/use-approve-anyway.d.ts +12 -0
  113. package/dist/hooks/use-approve-anyway.d.ts.map +1 -0
  114. package/dist/hooks/use-approve-anyway.js +81 -0
  115. package/dist/hooks/use-approve-anyway.js.map +1 -0
  116. package/dist/hooks/use-connection-problems.d.ts.map +1 -1
  117. package/dist/hooks/useAuth.d.ts +2 -2
  118. package/dist/hooks/useAuth.d.ts.map +1 -1
  119. package/dist/hooks/useAuth.js +2 -2
  120. package/dist/hooks/useAuth.js.map +1 -1
  121. package/dist/hooks/useOnboardingState.js +1 -1
  122. package/dist/hooks/useOnboardingState.js.map +1 -1
  123. package/dist/hooks/useValidateActionPlan.d.ts.map +1 -1
  124. package/dist/ldo-ui.d.ts +2 -1
  125. package/dist/ldo-ui.d.ts.map +1 -1
  126. package/dist/ldo-ui.js +1 -0
  127. package/dist/ldo-ui.js.map +1 -1
  128. package/dist/lib/datastore-route-table.d.ts +2 -1
  129. package/dist/lib/datastore-route-table.d.ts.map +1 -1
  130. package/dist/lib/datastore-route-table.js +2 -1
  131. package/dist/lib/datastore-route-table.js.map +1 -1
  132. package/dist/lib/manual-actions.d.ts +2 -1
  133. package/dist/lib/manual-actions.d.ts.map +1 -1
  134. package/dist/lib/manual-actions.js +3 -2
  135. package/dist/lib/manual-actions.js.map +1 -1
  136. package/dist/providers/ActiveChatProvider.js +3 -1
  137. package/dist/providers/ActiveChatProvider.js.map +1 -1
  138. package/dist/providers/AuthContext.d.ts +2 -1
  139. package/dist/providers/AuthContext.d.ts.map +1 -1
  140. package/dist/providers/AuthContext.js.map +1 -1
  141. package/dist/providers/ChatManagerProvider.d.ts.map +1 -1
  142. package/dist/providers/ChatManagerProvider.js +22 -9
  143. package/dist/providers/ChatManagerProvider.js.map +1 -1
  144. package/dist/providers/chat-socket-auth.d.ts +7 -2
  145. package/dist/providers/chat-socket-auth.d.ts.map +1 -1
  146. package/dist/providers/chat-socket-auth.js +87 -16
  147. package/dist/providers/chat-socket-auth.js.map +1 -1
  148. package/dist/providers/index.d.ts.map +1 -1
  149. package/dist/providers/index.js +8 -1
  150. package/dist/providers/index.js.map +1 -1
  151. package/dist/routes/activity/detail/ActivityChanges.d.ts +2 -0
  152. package/dist/routes/activity/detail/ActivityChanges.d.ts.map +1 -1
  153. package/dist/routes/activity/detail/ActivityChanges.js +8 -7
  154. package/dist/routes/activity/detail/ActivityChanges.js.map +1 -1
  155. package/dist/routes/activity/detail/ActivityDetail.d.ts +1 -0
  156. package/dist/routes/activity/detail/ActivityDetail.d.ts.map +1 -1
  157. package/dist/routes/activity/detail/ActivityDetail.js +5 -4
  158. package/dist/routes/activity/detail/ActivityDetail.js.map +1 -1
  159. package/dist/routes/activity/detail/ActivityStepsRail.d.ts +1 -0
  160. package/dist/routes/activity/detail/ActivityStepsRail.d.ts.map +1 -1
  161. package/dist/routes/activity/detail/ActivityStepsRail.js +3 -2
  162. package/dist/routes/activity/detail/ActivityStepsRail.js.map +1 -1
  163. package/dist/routes/activity/detail/ActivityTimeline.js +2 -2
  164. package/dist/routes/activity/detail/ActivityTimeline.js.map +1 -1
  165. package/dist/routes/activity/detail/NoChangesMessage.d.ts +6 -0
  166. package/dist/routes/activity/detail/NoChangesMessage.d.ts.map +1 -0
  167. package/dist/routes/activity/detail/NoChangesMessage.js +10 -0
  168. package/dist/routes/activity/detail/NoChangesMessage.js.map +1 -0
  169. package/dist/routes/data-explorer/components/RawTriples.js +1 -1
  170. package/dist/routes/data-explorer/components/RawTriples.js.map +1 -1
  171. package/dist/routes/data-explorer/components/RecentTypes.js +1 -1
  172. package/dist/routes/data-explorer/components/RecentTypes.js.map +1 -1
  173. package/dist/routes/data-explorer/components/class-detail/Instances.js +1 -1
  174. package/dist/routes/data-explorer/components/class-detail/Instances.js.map +1 -1
  175. package/dist/routes/data-explorer/components/namespace-detail/NamespaceClassRow.js +1 -1
  176. package/dist/routes/data-explorer/components/namespace-detail/NamespaceClassRow.js.map +1 -1
  177. package/dist/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.js +1 -1
  178. package/dist/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.js.map +1 -1
  179. package/dist/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.js +1 -1
  180. package/dist/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.js.map +1 -1
  181. package/dist/routes/data-explorer/components/record-detail/ChatPreview.js +2 -2
  182. package/dist/routes/data-explorer/components/record-detail/ChatPreview.js.map +1 -1
  183. package/dist/routes/data-explorer/declared-namespaces.d.ts +3 -0
  184. package/dist/routes/data-explorer/declared-namespaces.d.ts.map +1 -1
  185. package/dist/routes/data-explorer/declared-namespaces.js +21 -13
  186. package/dist/routes/data-explorer/declared-namespaces.js.map +1 -1
  187. package/dist/routes/data-explorer/namespaces.d.ts +1 -0
  188. package/dist/routes/data-explorer/namespaces.d.ts.map +1 -1
  189. package/dist/routes/data-explorer/namespaces.js +7 -6
  190. package/dist/routes/data-explorer/namespaces.js.map +1 -1
  191. package/dist/routes/datastores/components/DeleteDatastoreDialog.d.ts +10 -0
  192. package/dist/routes/datastores/components/DeleteDatastoreDialog.d.ts.map +1 -0
  193. package/dist/routes/datastores/components/DeleteDatastoreDialog.js +20 -0
  194. package/dist/routes/datastores/components/DeleteDatastoreDialog.js.map +1 -0
  195. package/dist/routes/datastores/flatten.d.ts +1 -0
  196. package/dist/routes/datastores/flatten.d.ts.map +1 -1
  197. package/dist/routes/datastores/flatten.js +17 -0
  198. package/dist/routes/datastores/flatten.js.map +1 -1
  199. package/dist/routes/datastores/hooks/useDatastoreColumns.d.ts +3 -1
  200. package/dist/routes/datastores/hooks/useDatastoreColumns.d.ts.map +1 -1
  201. package/dist/routes/datastores/hooks/useDatastoreColumns.js +14 -6
  202. package/dist/routes/datastores/hooks/useDatastoreColumns.js.map +1 -1
  203. package/dist/routes/datastores/index.d.ts.map +1 -1
  204. package/dist/routes/datastores/index.js +31 -5
  205. package/dist/routes/datastores/index.js.map +1 -1
  206. package/dist/routes/integrations/components/ProviderGroup.js +2 -2
  207. package/dist/routes/integrations/components/ProviderGroup.js.map +1 -1
  208. package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.d.ts.map +1 -1
  209. package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.js +13 -6
  210. package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.js.map +1 -1
  211. package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts +3 -0
  212. package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts.map +1 -1
  213. package/dist/routes/integrations/components/connect-forms/data-connection-fields.js +9 -2
  214. package/dist/routes/integrations/components/connect-forms/data-connection-fields.js.map +1 -1
  215. package/dist/routes/plans/components/ActionPlanPage.d.ts.map +1 -1
  216. package/dist/routes/plans/components/ActionPlanPage.js +4 -7
  217. package/dist/routes/plans/components/ActionPlanPage.js.map +1 -1
  218. package/dist/routes/plans/components/PlanDetailRouteContent.d.ts.map +1 -1
  219. package/dist/routes/plans/components/PlanDetailRouteContent.js +2 -1
  220. package/dist/routes/plans/components/PlanDetailRouteContent.js.map +1 -1
  221. package/package.json +12 -7
  222. package/src/app-subpaths.json +1 -0
  223. package/src/components/channel-icon/index.tsx +1 -1
  224. package/src/components/chat-view/ChatTurnErrorNotice.tsx +3 -1
  225. package/src/components/layouts/ConnectedCustomApp.tsx +63 -0
  226. package/src/components/layouts/Sidebar.tsx +9 -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/table-skeleton/index.tsx +7 -1
  232. package/src/components/tooltip/index.tsx +35 -2
  233. package/src/graph/createNodeRouter.tsx +3 -3
  234. package/src/graph/entity-link.tsx +20 -0
  235. package/src/graph/graph-list-utils.ts +2 -0
  236. package/src/graph/graph-model.ts +15 -6
  237. package/src/graph/nodes/BrandAssetAnalysisView.tsx +3 -1
  238. package/src/graph/nodes/{BrandFontFamilyView.tsx → BrandFontSuggestionView.tsx} +41 -27
  239. package/src/graph/nodes/BrandGuidelinesView.tsx +1 -1
  240. package/src/graph/nodes/NodePropertyTable.tsx +32 -143
  241. package/src/graph/nodes/brand-font.ts +17 -0
  242. package/src/graph/nodes/brand-shared.tsx +1 -4
  243. package/src/graph/nodes/node-property-row.tsx +154 -0
  244. package/src/graph/property-formatters.ts +5 -1
  245. package/src/graph/special-nodes/AttributeList.tsx +177 -0
  246. package/src/graph/special-nodes/EntityPreview.tsx +27 -0
  247. package/src/graph/special-nodes/EntityValueChip.tsx +85 -0
  248. package/src/graph/special-nodes/GenericView.tsx +49 -139
  249. package/src/graph/special-nodes/card-facts.ts +278 -0
  250. package/src/graph/special-nodes/property-icons.ts +59 -0
  251. package/src/graph/status-utils.ts +40 -0
  252. package/src/graph/types.ts +4 -0
  253. package/src/hooks/use-approve-anyway.ts +100 -0
  254. package/src/hooks/useAuth.ts +3 -3
  255. package/src/hooks/useOnboardingState.ts +1 -1
  256. package/src/ldo-ui.ts +8 -0
  257. package/src/lib/datastore-route-table.ts +4 -2
  258. package/src/lib/manual-actions.ts +3 -2
  259. package/src/providers/ActiveChatProvider.tsx +3 -1
  260. package/src/providers/AuthContext.ts +3 -1
  261. package/src/providers/ChatManagerProvider.tsx +19 -9
  262. package/src/providers/chat-socket-auth.ts +95 -16
  263. package/src/providers/index.tsx +16 -1
  264. package/src/routes/activity/detail/ActivityChanges.tsx +21 -5
  265. package/src/routes/activity/detail/ActivityDetail.tsx +24 -5
  266. package/src/routes/activity/detail/ActivityStepsRail.tsx +4 -2
  267. package/src/routes/activity/detail/ActivityTimeline.tsx +2 -2
  268. package/src/routes/activity/detail/NoChangesMessage.tsx +20 -0
  269. package/src/routes/data-explorer/components/RawTriples.tsx +1 -1
  270. package/src/routes/data-explorer/components/RecentTypes.tsx +1 -1
  271. package/src/routes/data-explorer/components/class-detail/Instances.tsx +1 -1
  272. package/src/routes/data-explorer/components/namespace-detail/NamespaceClassRow.tsx +1 -1
  273. package/src/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.tsx +1 -1
  274. package/src/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.tsx +1 -1
  275. package/src/routes/data-explorer/components/record-detail/ChatPreview.tsx +2 -2
  276. package/src/routes/data-explorer/declared-namespaces.ts +21 -13
  277. package/src/routes/data-explorer/namespaces.ts +7 -6
  278. package/src/routes/datastores/components/DeleteDatastoreDialog.tsx +78 -0
  279. package/src/routes/datastores/flatten.ts +15 -0
  280. package/src/routes/datastores/hooks/useDatastoreColumns.tsx +88 -49
  281. package/src/routes/datastores/index.tsx +41 -2
  282. package/src/routes/integrations/components/ProviderGroup.tsx +2 -2
  283. package/src/routes/integrations/components/connect-forms/DataConnectionConnectForm.tsx +38 -12
  284. package/src/routes/integrations/components/connect-forms/data-connection-fields.ts +11 -2
  285. package/src/routes/plans/components/ActionPlanPage.tsx +9 -8
  286. package/src/routes/plans/components/PlanDetailRouteContent.tsx +4 -3
  287. package/dist/components/planning/ExecutionActivityRow.d.ts +0 -9
  288. package/dist/components/planning/ExecutionActivityRow.d.ts.map +0 -1
  289. package/dist/components/planning/ExecutionActivityRow.js +0 -53
  290. package/dist/components/planning/ExecutionActivityRow.js.map +0 -1
  291. package/dist/components/planning/ExecutionSectionItem.d.ts +0 -20
  292. package/dist/components/planning/ExecutionSectionItem.d.ts.map +0 -1
  293. package/dist/components/planning/ExecutionSectionItem.js +0 -66
  294. package/dist/components/planning/ExecutionSectionItem.js.map +0 -1
  295. package/dist/components/planning/ExecutionSections.d.ts +0 -16
  296. package/dist/components/planning/ExecutionSections.d.ts.map +0 -1
  297. package/dist/components/planning/ExecutionSections.js +0 -32
  298. package/dist/components/planning/ExecutionSections.js.map +0 -1
  299. package/dist/components/planning/action-plan-icons.d.ts +0 -3
  300. package/dist/components/planning/action-plan-icons.d.ts.map +0 -1
  301. package/dist/components/planning/action-plan-icons.js +0 -25
  302. package/dist/components/planning/action-plan-icons.js.map +0 -1
  303. package/dist/components/planning/execution-section-model.d.ts +0 -24
  304. package/dist/components/planning/execution-section-model.d.ts.map +0 -1
  305. package/dist/components/planning/execution-section-model.js +0 -150
  306. package/dist/components/planning/execution-section-model.js.map +0 -1
  307. package/dist/graph/nodes/BrandFontFamilyView.d.ts +0 -3
  308. package/dist/graph/nodes/BrandFontFamilyView.d.ts.map +0 -1
  309. package/dist/graph/nodes/BrandFontFamilyView.js.map +0 -1
  310. package/dist/graph/nodes/BrandFontUploadButton.d.ts +0 -6
  311. package/dist/graph/nodes/BrandFontUploadButton.d.ts.map +0 -1
  312. package/dist/graph/nodes/BrandFontUploadButton.js +0 -69
  313. package/dist/graph/nodes/BrandFontUploadButton.js.map +0 -1
  314. package/dist/routes/data-explorer/components/TruncateTooltip.d.ts +0 -7
  315. package/dist/routes/data-explorer/components/TruncateTooltip.d.ts.map +0 -1
  316. package/dist/routes/data-explorer/components/TruncateTooltip.js +0 -9
  317. package/dist/routes/data-explorer/components/TruncateTooltip.js.map +0 -1
  318. package/src/components/planning/ExecutionActivityRow.tsx +0 -89
  319. package/src/components/planning/ExecutionSectionItem.tsx +0 -184
  320. package/src/components/planning/ExecutionSections.tsx +0 -97
  321. package/src/components/planning/action-plan-icons.tsx +0 -27
  322. package/src/components/planning/execution-section-model.ts +0 -190
  323. package/src/graph/nodes/BrandFontUploadButton.tsx +0 -95
  324. package/src/routes/data-explorer/components/TruncateTooltip.tsx +0 -25
@@ -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;
@@ -9,14 +9,19 @@ export type TableSkeletonProps = {
9
9
  renderRow: (rowIndex: number) => ReactNode;
10
10
  withWrapper?: boolean;
11
11
  className?: string;
12
+ headerClassName?: string;
13
+ rowClassName?: string;
12
14
  };
13
15
 
14
16
  export function TableSkeleton(props: TableSkeletonProps) {
15
17
  const { gridColsClassName, headerColumnCount, rows = 8, renderRow, withWrapper = true, className } = props;
18
+ const { headerClassName, rowClassName } = props;
16
19
 
17
20
  const content = (
18
21
  <>
19
- <div className={cn("grid gap-3 border-b border-muted-border bg-faint px-4 py-3", gridColsClassName)}>
22
+ <div
23
+ className={cn("grid gap-3 border-b border-muted-border bg-faint px-4 py-3", gridColsClassName, headerClassName)}
24
+ >
20
25
  {Array.from({ length: headerColumnCount }, (_, index) => (
21
26
  <Skeleton key={`table-skeleton-header-${index}`} className="h-4 w-2/3 rounded-md" />
22
27
  ))}
@@ -27,6 +32,7 @@ export function TableSkeleton(props: TableSkeletonProps) {
27
32
  className={cn(
28
33
  "grid items-center gap-3 border-b border-muted-border px-4 py-4 last:border-b-0",
29
34
  gridColsClassName,
35
+ rowClassName,
30
36
  )}
31
37
  >
32
38
  {renderRow(rowIndex)}
@@ -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
+ }
@@ -12,7 +12,7 @@ import { AttioNoteView } from "./nodes/AttioNoteView";
12
12
  import { AttioTaskView } from "./nodes/AttioTaskView";
13
13
  import { BrandAssetAnalysisActionView } from "./nodes/BrandAssetAnalysisActionView";
14
14
  import { BrandAssetAnalysisView } from "./nodes/BrandAssetAnalysisView";
15
- import { BrandFontFamilyView } from "./nodes/BrandFontFamilyView";
15
+ import { BrandFontSuggestionView } from "./nodes/BrandFontSuggestionView";
16
16
  import { BrandGuidelinesView } from "./nodes/BrandGuidelinesView";
17
17
  import { CoresignalCompanyView } from "./nodes/CoresignalCompanyView";
18
18
  import { CoresignalEmployeeView } from "./nodes/CoresignalEmployeeView";
@@ -123,7 +123,7 @@ const typedNodeEntries: ReadonlyArray<readonly [IRI, EntityView]> = [
123
123
  // Asserted by a Datalog rule, not by a node shape, so codegen emits no class term for it.
124
124
  [expandPrefix("brand:AssetAnalysis"), BrandAssetAnalysisView],
125
125
  [brand.BrandGuidelines, BrandGuidelinesView],
126
- [brand.FontFamily, BrandFontFamilyView],
126
+ [brand.FontSuggestion, BrandFontSuggestionView],
127
127
  ];
128
128
 
129
129
  export const typedEntityTypeIris: ReadonlySet<IRI> = new Set(typedNodeEntries.map(([type]) => type as IRI));
@@ -135,7 +135,7 @@ export const diffSubsumingViewIris: ReadonlySet<IRI> = new Set([
135
135
  expandPrefix("brand:AssetAnalysisShape"),
136
136
  expandPrefix("brand:AssetAnalysis"),
137
137
  brand.BrandGuidelines,
138
- brand.FontFamily,
138
+ brand.FontSuggestion,
139
139
  ]);
140
140
 
141
141
  export const typedActionShapeIris: ReadonlySet<IRI> = new Set(actionShapeNodeEntries.map(([iri]) => iri));
@@ -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>
@@ -1,4 +1,4 @@
1
- import { BrandFontFileSchema } from "@manta-eu/ldo";
1
+ import { BrandFontFileSchema, BrandSuggestedWeightSchema } from "@manta-eu/ldo";
2
2
  import { redirectPath } from "@manta-eu/ldo/redirect-queries";
3
3
  import { isPresent } from "@manta-eu/lib/present";
4
4
  import { namespaces } from "@manta-eu/rdf-lib/namespaces";
@@ -8,11 +8,13 @@ import type { EntityViewProps } from "../types";
8
8
  import {
9
9
  fontFaceDescriptors,
10
10
  preferredFontFile,
11
+ sortedWeights,
11
12
  specimenWeight,
13
+ weightLabel,
12
14
  type StoredFontFile,
15
+ type SuggestedWeight,
13
16
  } from "./brand-font";
14
17
  import { BrandNodeBody, BrandStatusBadge } from "./brand-shared";
15
- import { BrandFontUploadButton } from "./BrandFontUploadButton";
16
18
  import { EntityCardShell } from "./EntityCardShell";
17
19
  import { NodePropertyTable } from "./NodePropertyTable";
18
20
  import { readBrandString, toIriArray } from "./typed-node-helpers";
@@ -20,11 +22,27 @@ import { useEntitiesByIris } from "#hooks/use-entity";
20
22
  import { useFontFace } from "#hooks/use-font-face";
21
23
  import { useRedirectEndpoint } from "#hooks/use-redirect-endpoint";
22
24
 
23
- const statusPredicate = `${namespaces.brand}entryStatus`;
24
- const availabilityPredicate = `${namespaces.brand}fontAvailability`;
25
- const fontFilePredicate = `${namespaces.brand}fontFile`;
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
 
29
+ function useSuggestedWeights(iris: string[]): SuggestedWeight[] {
30
+ const { data } = useEntitiesByIris({ schema: BrandSuggestedWeightSchema, iris });
31
+
32
+ return (data ?? []).flatMap((weight) =>
33
+ weight
34
+ ? [
35
+ {
36
+ weight: weight.fontWeight,
37
+ style: weight.fontStyle,
38
+ availability: weight.fontAvailability,
39
+ coveringFiles: weight.coveringFile ?? [],
40
+ },
41
+ ]
42
+ : [],
43
+ );
44
+ }
45
+
28
46
  function useStoredFontFiles(iris: string[]): StoredFontFile[] {
29
47
  const { data } = useEntitiesByIris({ schema: BrandFontFileSchema, iris });
30
48
 
@@ -69,47 +87,43 @@ function FontSpecimen(props: FontSpecimenProps) {
69
87
  );
70
88
  }
71
89
 
72
- export const BrandFontFamilyView = memo(function BrandFontFamilyView(props: EntityViewProps) {
90
+ export const BrandFontSuggestionView = memo(function BrandFontSuggestionView(props: EntityViewProps) {
73
91
  const { data, selected = false, ringColor, onContextMenu } = props;
74
92
 
75
93
  const family = readBrandString(data.jsonLd, "family") ?? data.label;
76
- const status = readBrandString(data.jsonLd, "entryStatus");
77
- const availability = readBrandString(data.jsonLd, "fontAvailability");
78
- const fileIris = toIriArray(data.jsonLd[fontFilePredicate] ?? data.jsonLd["brand:fontFile"]);
79
- const file = preferredFontFile(useStoredFontFiles(fileIris));
94
+ const weights = sortedWeights(
95
+ useSuggestedWeights(toIriArray(data.jsonLd[weightPredicate] ?? data.jsonLd["brand:hasSuggestedWeight"])),
96
+ );
97
+ const file = preferredFontFile(useStoredFontFiles([...new Set(weights.flatMap((weight) => weight.coveringFiles))]));
80
98
 
81
99
  return (
82
100
  <EntityCardShell
83
101
  icon={Type}
84
- label={`Font Family: ${family}`}
102
+ label={`Font Suggestion: ${family}`}
85
103
  labelMaxWidth="max-w-140"
86
104
  selected={selected}
87
105
  ringColor={ringColor}
88
106
  onContextMenu={onContextMenu}
89
107
  >
90
- <BrandNodeBody
91
- right={
92
- <div className="flex items-center gap-1">
93
- <BrandStatusBadge status={availability} />
94
- <BrandStatusBadge status={status} />
95
- </div>
96
- }
97
- >
108
+ <BrandNodeBody>
98
109
  {isPresent(file) && <FontSpecimen file={file} />}
99
110
 
100
- {isPresent(availability) && availability !== "available" && (
101
- <div className="flex items-center justify-between gap-2">
102
- {availability === "needs-upload" && (
103
- <span className="typography-tiny text-muted-foreground">No font file found for this family.</span>
104
- )}
105
- <BrandFontUploadButton family={family} />
106
- </div>
111
+ {isPresent(weights) && (
112
+ <ul className="flex flex-col gap-1">
113
+ {weights.map((weight) => (
114
+ <li key={weightLabel(weight)} className="flex items-center justify-between gap-2">
115
+ <span className="typography-tiny text-default-foreground">{weightLabel(weight)}</span>
116
+ <BrandStatusBadge status={weight.availability} />
117
+ </li>
118
+ ))}
119
+ </ul>
107
120
  )}
108
121
 
109
122
  <NodePropertyTable
110
123
  properties={data.properties}
111
124
  jsonLd={data.jsonLd}
112
- omitPredicates={[statusPredicate, availabilityPredicate]}
125
+ relations={data.relations}
126
+ omitPredicates={listedElsewhere}
113
127
  />
114
128
  </BrandNodeBody>
115
129
  </EntityCardShell>
@@ -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
  );
@@ -1,15 +1,16 @@
1
- import { isPresent } from "@manta-eu/lib/present";
2
- import { Check, ChevronDown, ChevronRight, X } from "lucide-react";
3
- import { useMemo, useState } from "react";
4
- import { match, P } from "ts-pattern";
1
+ import { useCallback, useMemo } from "react";
5
2
  import { shouldHidePreviewField } from "../graph-list-utils";
6
- import { ontologyTermIrisForProperties, withOntologyLabels } from "../ontology-labels";
7
- import { formatDisplayValue } from "../property-formatters";
8
- import type { NodeProperty } from "../types";
9
- import { classifyPropertyDisplay, type PropertyDisplay } from "./node-property-display";
10
- import { useOntologyTerms } from "#hooks/use-ontology-terms";
11
- import { formatPropertyLabel } from "#lib/iri-labels";
12
- import { cn } from "#style";
3
+ import { AttributeList, useAttributeFacts } from "../special-nodes/AttributeList";
4
+ import type { NodeProperty, NodeRelation } from "../types";
5
+
6
+ export {
7
+ NodePropertyExpander,
8
+ NodePropertyList,
9
+ NodePropertyRow,
10
+ PropertyValue,
11
+ type NodePropertyExpanderProps,
12
+ type NodePropertyRowProps,
13
+ } from "./node-property-row";
13
14
 
14
15
  export type NodePropertyTableProps = {
15
16
  properties: NodeProperty[];
@@ -17,145 +18,33 @@ export type NodePropertyTableProps = {
17
18
  jsonLd?: Record<string, unknown>;
18
19
  // Rendered above the table by the card itself, so the table skips them.
19
20
  omitPredicates?: readonly string[];
21
+ relations?: NodeRelation[];
20
22
  };
21
23
 
22
- function Tag(props: { children: string }) {
23
- return (
24
- <span className="rounded bg-faint px-1.5 py-[1px] typography-tiny text-default-foreground">{props.children}</span>
25
- );
26
- }
27
-
28
- function PropertyValue(props: { display: PropertyDisplay }) {
29
- return match(props.display)
30
- .with({ kind: "tags" }, ({ values }) => (
31
- <div className="flex flex-wrap gap-1">
32
- {values.map((value) => (
33
- <Tag key={value}>{value}</Tag>
34
- ))}
35
- </div>
36
- ))
37
- .with({ kind: "color" }, ({ hex }) => (
38
- <span className="flex items-center gap-1.5">
39
- <span
40
- aria-hidden
41
- className="size-3.5 shrink-0 rounded-sm border border-default-border"
42
- style={{ backgroundColor: hex }}
43
- />
44
- <span className="tabular-nums">{hex}</span>
45
- </span>
46
- ))
47
- .with({ kind: "ratio" }, ({ fraction, text }) => (
48
- <span className="flex items-center gap-1.5">
49
- <span aria-hidden className="h-1 w-12 shrink-0 overflow-hidden rounded-full bg-faint">
50
- <span className="block h-full rounded-full bg-accent-foreground" style={{ width: `${fraction * 100}%` }} />
51
- </span>
52
- <span className="tabular-nums">{text}</span>
53
- </span>
54
- ))
55
- .with({ kind: "number" }, ({ text }) => <span className="tabular-nums">{text}</span>)
56
- .with({ kind: "boolean" }, ({ value }) =>
57
- value ? (
58
- <span className="flex items-center gap-1">
59
- <Check aria-hidden className="size-3.5 shrink-0 text-success-foreground" />
60
- true
61
- </span>
62
- ) : (
63
- <span className="flex items-center gap-1">
64
- <X aria-hidden className="size-3.5 shrink-0 text-muted-foreground" />
65
- false
66
- </span>
67
- ),
68
- )
69
- .with(P.union({ kind: "prose" }, { kind: "text" }), ({ text }) => <span>{text}</span>)
70
- .exhaustive();
71
- }
72
-
73
- type Row = { key: string; label: string; display: PropertyDisplay };
74
-
75
- function PropertyRow(props: { row: Row }) {
76
- const { row } = props;
77
-
78
- return (
79
- <div className="-mx-1 grid grid-cols-[minmax(0,7rem)_minmax(0,1fr)] items-baseline gap-x-3 gap-y-1 rounded-md border-t border-muted-border/50 px-1 py-1.5 transition-colors first:border-t-0 hover:bg-muted/30">
80
- <span className="typography-tiny min-w-0 break-words text-muted-foreground first-letter:uppercase">
81
- {row.label}
82
- </span>
83
- <div
84
- className={cn(
85
- "typography-tiny min-w-0 break-words text-default-foreground",
86
- // A long description reads better as its own full-width block under the label.
87
- row.display.kind === "prose" && "col-span-2",
88
- )}
89
- >
90
- <PropertyValue display={row.display} />
91
- </div>
92
- </div>
93
- );
94
- }
24
+ const noJsonLd: Record<string, unknown> = {};
95
25
 
96
- // Every property the node carries, laid out like the record-detail field list. Rule-derived
26
+ // Every property the node carries, in the same attribute list the fallback card uses. Rule-derived
97
27
  // properties are included: they are real on the instance even though no shape declares them.
98
- // Short values keep the compact two-column rhythm; prose paragraphs collapse behind the same
99
- // "Show more" expander AttioNodeBody uses, so the card stays a summary until asked.
100
28
  export function NodePropertyTable(props: NodePropertyTableProps) {
101
- const { properties, jsonLd, omitPredicates = [] } = props;
29
+ const { properties, jsonLd = noJsonLd, omitPredicates, relations } = props;
102
30
 
103
- const [expanded, setExpanded] = useState(false);
104
-
105
- const terms = useOntologyTerms(useMemo(() => ontologyTermIrisForProperties(properties), [properties]));
106
-
107
- const rows = useMemo(() => {
108
- const omitted = new Set(omitPredicates);
109
-
110
- return withOntologyLabels(properties, terms)
111
- .filter(
112
- (property) =>
113
- !omitted.has(property.iri ?? "") && !shouldHidePreviewField(property.label ?? "", property.iri ?? ""),
114
- )
115
- .map((property): Row => {
116
- const label = property.label || formatPropertyLabel(property.iri ?? property.key);
117
- const formatted = formatDisplayValue(property.value, {
118
- predicate: property.iri,
119
- predicateLabel: property.label,
120
- valueScale: property.valueScale,
121
- });
122
-
123
- return {
124
- key: property.iri ?? property.key,
125
- label,
126
- display: classifyPropertyDisplay({ label, formatted, raw: jsonLd?.[property.iri ?? ""] ?? property.value }),
127
- };
128
- });
129
- }, [properties, terms, jsonLd, omitPredicates]);
130
-
131
- const compactRows = rows.filter((row) => row.display.kind !== "prose");
132
- const proseRows = rows.filter((row) => row.display.kind === "prose");
31
+ const include = useCallback(
32
+ (property: NodeProperty) =>
33
+ !(omitPredicates ?? []).includes(property.iri ?? "") &&
34
+ !shouldHidePreviewField(property.label ?? "", property.iri ?? ""),
35
+ [omitPredicates],
36
+ );
133
37
 
134
- if (!isPresent(rows)) return null;
38
+ const visibleRelations = useMemo(
39
+ () =>
40
+ relations?.filter(
41
+ (relation) =>
42
+ !(omitPredicates ?? []).includes(relation.predicate) && !shouldHidePreviewField("", relation.predicate),
43
+ ),
44
+ [relations, omitPredicates],
45
+ );
135
46
 
136
- return (
137
- <div className="flex flex-col">
138
- {compactRows.map((row) => (
139
- <PropertyRow key={row.key} row={row} />
140
- ))}
47
+ const { facts, previewCount } = useAttributeFacts({ properties, relations: visibleRelations, jsonLd, include });
141
48
 
142
- {isPresent(proseRows) && (
143
- <>
144
- {expanded && proseRows.map((row) => <PropertyRow key={row.key} row={row} />)}
145
- <button
146
- type="button"
147
- onClick={() => setExpanded((value) => !value)}
148
- className="nodrag flex items-center gap-1 pt-1.5 typography-tiny-medium text-muted-foreground hover:text-default-foreground"
149
- >
150
- {expanded ? (
151
- <ChevronDown size={11} className="shrink-0" />
152
- ) : (
153
- <ChevronRight size={11} className="shrink-0" />
154
- )}
155
- {expanded ? "Show less" : `Show ${proseRows.length} more`}
156
- </button>
157
- </>
158
- )}
159
- </div>
160
- );
49
+ return <AttributeList facts={facts} previewCount={previewCount} showAll />;
161
50
  }
@@ -27,3 +27,20 @@ export function fontFaceDescriptors(file: StoredFontFile): FontFaceDescriptors {
27
27
  export function specimenWeight(file: StoredFontFile): number {
28
28
  return Math.min(Math.max(400, file.weightMin), file.weightMax);
29
29
  }
30
+
31
+ export type SuggestedWeight = {
32
+ weight: number;
33
+ style: "normal" | "italic";
34
+ availability: "available" | "looking-up" | "needs-upload";
35
+ coveringFiles: readonly string[];
36
+ };
37
+
38
+ export function sortedWeights<W extends Pick<SuggestedWeight, "weight" | "style">>(weights: readonly W[]): W[] {
39
+ return [...weights].sort(
40
+ (a, b) => a.weight - b.weight || Number(a.style === "italic") - Number(b.style === "italic"),
41
+ );
42
+ }
43
+
44
+ export function weightLabel(weight: Pick<SuggestedWeight, "weight" | "style">): string {
45
+ return weight.style === "italic" ? `${weight.weight} italic` : `${weight.weight}`;
46
+ }
@@ -11,14 +11,11 @@ import { cn } from "#style";
11
11
 
12
12
  export const brandAmber = "#d97706";
13
13
 
14
- // Every `sh:in` value on the brand status paths in kgc/shacl/shapes/brand.ttl; an unlisted one means a shape moved on.
14
+ // Every `sh:in` value of brand:fontAvailability in kgc/shacl/shapes/brand-font-suggestion.ttl.
15
15
  const toneByStatus = {
16
- accepted: "positive",
17
16
  available: "positive",
18
- draft: "neutral",
19
17
  "looking-up": "neutral",
20
18
  "needs-upload": "caution",
21
- rejected: "negative",
22
19
  } as const satisfies Record<string, BadgeTone>;
23
20
 
24
21
  export type BrandStatus = keyof typeof toneByStatus;