@vertesia/ui 0.78.0 → 0.79.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 (409) hide show
  1. package/lib/esm/core/components/Panel.js +8 -0
  2. package/lib/esm/core/components/Panel.js.map +1 -0
  3. package/lib/esm/core/components/SelectBox.js +1 -1
  4. package/lib/esm/core/components/SelectBox.js.map +1 -1
  5. package/lib/esm/core/components/SelectList.js +18 -13
  6. package/lib/esm/core/components/SelectList.js.map +1 -1
  7. package/lib/esm/core/components/SidePanel.js +2 -2
  8. package/lib/esm/core/components/SidePanel.js.map +1 -1
  9. package/lib/esm/core/components/index.js +1 -1
  10. package/lib/esm/core/components/index.js.map +1 -1
  11. package/lib/esm/core/components/shadcn/breadcrumb.js +29 -8
  12. package/lib/esm/core/components/shadcn/breadcrumb.js.map +1 -1
  13. package/lib/esm/core/components/shadcn/button.js +3 -2
  14. package/lib/esm/core/components/shadcn/button.js.map +1 -1
  15. package/lib/esm/core/components/shadcn/filters/filterBar.js +41 -14
  16. package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
  17. package/lib/esm/core/components/shadcn/index.js +2 -0
  18. package/lib/esm/core/components/shadcn/index.js.map +1 -1
  19. package/lib/esm/core/components/shadcn/input.js +4 -1
  20. package/lib/esm/core/components/shadcn/input.js.map +1 -1
  21. package/lib/esm/core/components/shadcn/resizeable.js +15 -0
  22. package/lib/esm/core/components/shadcn/resizeable.js.map +1 -0
  23. package/lib/esm/core/components/shadcn/selectBox.js +15 -9
  24. package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
  25. package/lib/esm/core/components/shadcn/tabs.js +20 -8
  26. package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
  27. package/lib/esm/core/components/shadcn/textarea.js +7 -0
  28. package/lib/esm/core/components/shadcn/textarea.js.map +1 -0
  29. package/lib/esm/core/components/table/index.js +1 -1
  30. package/lib/esm/core/components/table/index.js.map +1 -1
  31. package/lib/esm/core/hooks/CompositeState.js +139 -1
  32. package/lib/esm/core/hooks/CompositeState.js.map +1 -1
  33. package/lib/esm/core/hooks/index.js +1 -0
  34. package/lib/esm/core/hooks/index.js.map +1 -1
  35. package/lib/esm/core/hooks/useScrollableSearch.js +92 -0
  36. package/lib/esm/core/hooks/useScrollableSearch.js.map +1 -0
  37. package/lib/esm/env/index.js +1 -1
  38. package/lib/esm/env/index.js.map +1 -1
  39. package/lib/esm/features/agent/PayloadBuilder.js +80 -55
  40. package/lib/esm/features/agent/PayloadBuilder.js.map +1 -1
  41. package/lib/esm/features/agent/chat/ModernAgentConversation.js +22 -24
  42. package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
  43. package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +2 -3
  44. package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  45. package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +2 -2
  46. package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  47. package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +15 -20
  48. package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
  49. package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js +1 -0
  50. package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js.map +1 -1
  51. package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js +3 -3
  52. package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js.map +1 -1
  53. package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +6 -6
  54. package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  55. package/lib/esm/features/facets/CollectionsFacetsNav.js +85 -0
  56. package/lib/esm/features/facets/CollectionsFacetsNav.js.map +1 -0
  57. package/lib/esm/features/facets/DocumentsFacetsNav.js +19 -7
  58. package/lib/esm/features/facets/DocumentsFacetsNav.js.map +1 -1
  59. package/lib/esm/features/facets/EnvironmentFacet.js +1 -1
  60. package/lib/esm/features/facets/EnvironmentFacet.js.map +1 -1
  61. package/lib/esm/features/facets/InteractionsFacetsNav.js +88 -0
  62. package/lib/esm/features/facets/InteractionsFacetsNav.js.map +1 -0
  63. package/lib/esm/features/facets/PromptsFacetsNav.js +80 -0
  64. package/lib/esm/features/facets/PromptsFacetsNav.js.map +1 -0
  65. package/lib/esm/features/facets/RunsFacetsNav.js +28 -6
  66. package/lib/esm/features/facets/RunsFacetsNav.js.map +1 -1
  67. package/lib/esm/features/facets/WorkflowExecutionsFacetsNav.js +7 -5
  68. package/lib/esm/features/facets/WorkflowExecutionsFacetsNav.js.map +1 -1
  69. package/lib/esm/features/facets/index.js +10 -8
  70. package/lib/esm/features/facets/index.js.map +1 -1
  71. package/lib/esm/features/facets/utils/SearchInterface.js +2 -0
  72. package/lib/esm/features/facets/utils/SearchInterface.js.map +1 -0
  73. package/lib/esm/features/facets/utils/StringFacet.js.map +1 -0
  74. package/lib/esm/features/facets/utils/StringListFacet.js.map +1 -0
  75. package/lib/esm/features/facets/utils/TypeFacet.js.map +1 -0
  76. package/lib/esm/features/facets/utils/VEnvironmentFacet.js.map +1 -0
  77. package/lib/esm/features/facets/utils/VInteractionFacet.js.map +1 -0
  78. package/lib/esm/features/facets/utils/VStringFacet.js.map +1 -0
  79. package/lib/esm/features/facets/{VTypeFacet.js → utils/VTypeFacet.js} +9 -4
  80. package/lib/esm/features/facets/utils/VTypeFacet.js.map +1 -0
  81. package/lib/esm/features/facets/{VUserFacet.js → utils/VUserFacet.js} +1 -1
  82. package/lib/esm/features/facets/utils/VUserFacet.js.map +1 -0
  83. package/lib/esm/features/facets/utils/utils.js.map +1 -0
  84. package/lib/esm/features/layout/GenericPageNavHeader.js +58 -5
  85. package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -1
  86. package/lib/esm/features/store/collections/BrowseCollectionView.js +3 -0
  87. package/lib/esm/features/store/collections/BrowseCollectionView.js.map +1 -1
  88. package/lib/esm/features/store/collections/CreateCollection.js +2 -2
  89. package/lib/esm/features/store/collections/CreateCollection.js.map +1 -1
  90. package/lib/esm/features/store/collections/EditCollectionView.js +43 -31
  91. package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
  92. package/lib/esm/features/store/collections/SelectCollection.js +46 -16
  93. package/lib/esm/features/store/collections/SelectCollection.js.map +1 -1
  94. package/lib/esm/features/store/objects/DocumentSearchResults.js +43 -13
  95. package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
  96. package/lib/esm/features/store/objects/DocumentTable.js +6 -6
  97. package/lib/esm/features/store/objects/DocumentTable.js.map +1 -1
  98. package/lib/esm/features/store/objects/components/ContentOverview.js +225 -87
  99. package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
  100. package/lib/esm/features/store/objects/components/DocumentIcon.js +11 -3
  101. package/lib/esm/features/store/objects/components/DocumentIcon.js.map +1 -1
  102. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js +11 -2
  103. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -1
  104. package/lib/esm/features/store/objects/components/useDownloadObject.js +2 -2
  105. package/lib/esm/features/store/objects/components/useDownloadObject.js.map +1 -1
  106. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +13 -1
  107. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  108. package/lib/esm/features/store/objects/layout/documentLayout.js +7 -8
  109. package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -1
  110. package/lib/esm/features/store/objects/layout/renderers.js +28 -12
  111. package/lib/esm/features/store/objects/layout/renderers.js.map +1 -1
  112. package/lib/esm/features/store/objects/search/DocumentSearchContext.js +5 -1
  113. package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  114. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js +1 -1
  115. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js.map +1 -1
  116. package/lib/esm/features/store/objects/selection/ObjectsActionContext.js +3 -2
  117. package/lib/esm/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
  118. package/lib/esm/features/store/objects/selection/SelectionActions.js +2 -0
  119. package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
  120. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js +12 -4
  121. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js.map +1 -1
  122. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js +20 -2
  123. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
  124. package/lib/esm/features/store/objects/upload/DocumentUploadModal.js +16 -8
  125. package/lib/esm/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
  126. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js +1 -1
  127. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js.map +1 -1
  128. package/lib/esm/features/store/types/ObjectSchemaEditor.js +1 -1
  129. package/lib/esm/features/store/types/ObjectSchemaEditor.js.map +1 -1
  130. package/lib/esm/features/user/UserInfo.js +35 -1
  131. package/lib/esm/features/user/UserInfo.js.map +1 -1
  132. package/lib/esm/router/HistoryNavigator.js +25 -2
  133. package/lib/esm/router/HistoryNavigator.js.map +1 -1
  134. package/lib/esm/router/Nav.js +3 -3
  135. package/lib/esm/router/Nav.js.map +1 -1
  136. package/lib/esm/session/UserSession.js +1 -0
  137. package/lib/esm/session/UserSession.js.map +1 -1
  138. package/lib/esm/session/UserSessionProvider.js +9 -2
  139. package/lib/esm/session/UserSessionProvider.js.map +1 -1
  140. package/lib/esm/session/auth/composable.js +66 -67
  141. package/lib/esm/session/auth/composable.js.map +1 -1
  142. package/lib/esm/shell/login/UserInfo.js +1 -1
  143. package/lib/esm/shell/login/UserInfo.js.map +1 -1
  144. package/lib/esm/widgets/form/Form.js +17 -30
  145. package/lib/esm/widgets/form/Form.js.map +1 -1
  146. package/lib/esm/widgets/form/FormContext.js +4 -2
  147. package/lib/esm/widgets/form/FormContext.js.map +1 -1
  148. package/lib/esm/widgets/form/ManagedObject.js +4 -0
  149. package/lib/esm/widgets/form/ManagedObject.js.map +1 -1
  150. package/lib/esm/widgets/form/fields.js +4 -3
  151. package/lib/esm/widgets/form/fields.js.map +1 -1
  152. package/lib/esm/widgets/form/inputs.js +2 -0
  153. package/lib/esm/widgets/form/inputs.js.map +1 -1
  154. package/lib/esm/widgets/schema-editor/index.js +0 -1
  155. package/lib/esm/widgets/schema-editor/index.js.map +1 -1
  156. package/lib/tsconfig.tsbuildinfo +1 -1
  157. package/lib/types/core/components/Panel.d.ts +11 -0
  158. package/lib/types/core/components/Panel.d.ts.map +1 -0
  159. package/lib/types/core/components/SelectList.d.ts +2 -1
  160. package/lib/types/core/components/SelectList.d.ts.map +1 -1
  161. package/lib/types/core/components/SidePanel.d.ts.map +1 -1
  162. package/lib/types/core/components/index.d.ts +1 -1
  163. package/lib/types/core/components/index.d.ts.map +1 -1
  164. package/lib/types/core/components/shadcn/breadcrumb.d.ts +3 -2
  165. package/lib/types/core/components/shadcn/breadcrumb.d.ts.map +1 -1
  166. package/lib/types/core/components/shadcn/button.d.ts.map +1 -1
  167. package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  168. package/lib/types/core/components/shadcn/index.d.ts +2 -0
  169. package/lib/types/core/components/shadcn/index.d.ts.map +1 -1
  170. package/lib/types/core/components/shadcn/input.d.ts.map +1 -1
  171. package/lib/types/core/components/shadcn/resizeable.d.ts +9 -0
  172. package/lib/types/core/components/shadcn/resizeable.d.ts.map +1 -0
  173. package/lib/types/core/components/shadcn/selectBox.d.ts +3 -2
  174. package/lib/types/core/components/shadcn/selectBox.d.ts.map +1 -1
  175. package/lib/types/core/components/shadcn/tabs.d.ts +2 -1
  176. package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
  177. package/lib/types/core/components/shadcn/textarea.d.ts +4 -0
  178. package/lib/types/core/components/shadcn/textarea.d.ts.map +1 -0
  179. package/lib/types/core/hooks/CompositeState.d.ts +115 -6
  180. package/lib/types/core/hooks/CompositeState.d.ts.map +1 -1
  181. package/lib/types/core/hooks/index.d.ts +1 -0
  182. package/lib/types/core/hooks/index.d.ts.map +1 -1
  183. package/lib/types/core/hooks/useScrollableSearch.d.ts +82 -0
  184. package/lib/types/core/hooks/useScrollableSearch.d.ts.map +1 -0
  185. package/lib/types/env/index.d.ts +3 -1
  186. package/lib/types/env/index.d.ts.map +1 -1
  187. package/lib/types/features/agent/PayloadBuilder.d.ts +11 -19
  188. package/lib/types/features/agent/PayloadBuilder.d.ts.map +1 -1
  189. package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  190. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +1 -1
  191. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  192. package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
  193. package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
  194. package/lib/types/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts.map +1 -1
  195. package/lib/types/features/facets/CollectionsFacetsNav.d.ts +14 -0
  196. package/lib/types/features/facets/CollectionsFacetsNav.d.ts.map +1 -0
  197. package/lib/types/features/facets/DocumentsFacetsNav.d.ts +1 -1
  198. package/lib/types/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
  199. package/lib/types/features/facets/InteractionsFacetsNav.d.ts +14 -0
  200. package/lib/types/features/facets/InteractionsFacetsNav.d.ts.map +1 -0
  201. package/lib/types/features/facets/PromptsFacetsNav.d.ts +15 -0
  202. package/lib/types/features/facets/PromptsFacetsNav.d.ts.map +1 -0
  203. package/lib/types/features/facets/RunsFacetsNav.d.ts +1 -1
  204. package/lib/types/features/facets/RunsFacetsNav.d.ts.map +1 -1
  205. package/lib/types/features/facets/WorkflowExecutionsFacetsNav.d.ts +1 -1
  206. package/lib/types/features/facets/WorkflowExecutionsFacetsNav.d.ts.map +1 -1
  207. package/lib/types/features/facets/index.d.ts +10 -8
  208. package/lib/types/features/facets/index.d.ts.map +1 -1
  209. package/lib/types/features/facets/utils/SearchInterface.d.ts +14 -0
  210. package/lib/types/features/facets/utils/SearchInterface.d.ts.map +1 -0
  211. package/lib/types/features/facets/utils/StringFacet.d.ts.map +1 -0
  212. package/lib/types/features/facets/utils/StringListFacet.d.ts.map +1 -0
  213. package/lib/types/features/facets/utils/TypeFacet.d.ts.map +1 -0
  214. package/lib/types/features/facets/utils/VEnvironmentFacet.d.ts.map +1 -0
  215. package/lib/types/features/facets/utils/VInteractionFacet.d.ts.map +1 -0
  216. package/lib/types/features/facets/utils/VStringFacet.d.ts.map +1 -0
  217. package/lib/types/features/facets/{VTypeFacet.d.ts → utils/VTypeFacet.d.ts} +2 -1
  218. package/lib/types/features/facets/utils/VTypeFacet.d.ts.map +1 -0
  219. package/lib/types/features/facets/utils/VUserFacet.d.ts.map +1 -0
  220. package/lib/types/features/facets/utils/utils.d.ts.map +1 -0
  221. package/lib/types/features/layout/GenericPageNavHeader.d.ts +2 -1
  222. package/lib/types/features/layout/GenericPageNavHeader.d.ts.map +1 -1
  223. package/lib/types/features/store/collections/BrowseCollectionView.d.ts.map +1 -1
  224. package/lib/types/features/store/collections/CreateCollection.d.ts.map +1 -1
  225. package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
  226. package/lib/types/features/store/collections/SelectCollection.d.ts +12 -8
  227. package/lib/types/features/store/collections/SelectCollection.d.ts.map +1 -1
  228. package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  229. package/lib/types/features/store/objects/DocumentTable.d.ts +4 -0
  230. package/lib/types/features/store/objects/DocumentTable.d.ts.map +1 -1
  231. package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  232. package/lib/types/features/store/objects/components/DocumentIcon.d.ts +7 -1
  233. package/lib/types/features/store/objects/components/DocumentIcon.d.ts.map +1 -1
  234. package/lib/types/features/store/objects/components/SaveVersionConfirmModal.d.ts.map +1 -1
  235. package/lib/types/features/store/objects/components/useDownloadObject.d.ts +1 -1
  236. package/lib/types/features/store/objects/components/useDownloadObject.d.ts.map +1 -1
  237. package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts +2 -1
  238. package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  239. package/lib/types/features/store/objects/layout/documentLayout.d.ts +4 -2
  240. package/lib/types/features/store/objects/layout/documentLayout.d.ts.map +1 -1
  241. package/lib/types/features/store/objects/layout/renderers.d.ts +1 -1
  242. package/lib/types/features/store/objects/layout/renderers.d.ts.map +1 -1
  243. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +2 -3
  244. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  245. package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
  246. package/lib/types/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
  247. package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts +1 -0
  248. package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
  249. package/lib/types/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
  250. package/lib/types/features/user/UserInfo.d.ts +12 -1
  251. package/lib/types/features/user/UserInfo.d.ts.map +1 -1
  252. package/lib/types/router/HistoryNavigator.d.ts.map +1 -1
  253. package/lib/types/router/Nav.d.ts +2 -1
  254. package/lib/types/router/Nav.d.ts.map +1 -1
  255. package/lib/types/session/UserSession.d.ts.map +1 -1
  256. package/lib/types/session/UserSessionProvider.d.ts.map +1 -1
  257. package/lib/types/session/auth/composable.d.ts.map +1 -1
  258. package/lib/types/widgets/form/Form.d.ts +2 -1
  259. package/lib/types/widgets/form/Form.d.ts.map +1 -1
  260. package/lib/types/widgets/form/FormContext.d.ts +5 -2
  261. package/lib/types/widgets/form/FormContext.d.ts.map +1 -1
  262. package/lib/types/widgets/form/ManagedObject.d.ts.map +1 -1
  263. package/lib/types/widgets/form/fields.d.ts +2 -2
  264. package/lib/types/widgets/form/fields.d.ts.map +1 -1
  265. package/lib/types/widgets/form/inputs.d.ts.map +1 -1
  266. package/lib/types/widgets/schema-editor/index.d.ts +0 -1
  267. package/lib/types/widgets/schema-editor/index.d.ts.map +1 -1
  268. package/lib/vertesia-ui-core.js +1 -1
  269. package/lib/vertesia-ui-core.js.map +1 -1
  270. package/lib/vertesia-ui-env.js +1 -1
  271. package/lib/vertesia-ui-env.js.map +1 -1
  272. package/lib/vertesia-ui-features.js +1 -1
  273. package/lib/vertesia-ui-features.js.map +1 -1
  274. package/lib/vertesia-ui-router.js +1 -1
  275. package/lib/vertesia-ui-router.js.map +1 -1
  276. package/lib/vertesia-ui-session.js +1 -1
  277. package/lib/vertesia-ui-session.js.map +1 -1
  278. package/lib/vertesia-ui-shell.js +1 -1
  279. package/lib/vertesia-ui-shell.js.map +1 -1
  280. package/lib/vertesia-ui-widgets.js +1 -1
  281. package/lib/vertesia-ui-widgets.js.map +1 -1
  282. package/package.json +166 -165
  283. package/src/core/components/Panel.tsx +34 -0
  284. package/src/core/components/SelectList.tsx +11 -1
  285. package/src/core/components/SidePanel.tsx +18 -13
  286. package/src/core/components/index.ts +1 -1
  287. package/src/core/components/shadcn/breadcrumb.tsx +49 -30
  288. package/src/core/components/shadcn/button.tsx +3 -2
  289. package/src/core/components/shadcn/filters/filterBar.tsx +49 -23
  290. package/src/core/components/shadcn/index.ts +2 -0
  291. package/src/core/components/shadcn/input.tsx +10 -7
  292. package/src/core/components/shadcn/resizeable.tsx +54 -0
  293. package/src/core/components/shadcn/selectBox.tsx +87 -67
  294. package/src/core/components/shadcn/tabs.tsx +25 -8
  295. package/src/core/components/shadcn/textarea.tsx +21 -0
  296. package/src/core/components/table/index.tsx +1 -1
  297. package/src/core/hooks/index.ts +1 -0
  298. package/src/core/hooks/useScrollableSearch.tsx +193 -0
  299. package/src/features/agent/chat/ModernAgentConversation.tsx +109 -118
  300. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +2 -22
  301. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +1 -9
  302. package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +39 -55
  303. package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +1 -0
  304. package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +8 -8
  305. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +8 -8
  306. package/src/features/facets/CollectionsFacetsNav.tsx +115 -0
  307. package/src/features/facets/DocumentsFacetsNav.tsx +22 -11
  308. package/src/features/facets/EnvironmentFacet.tsx +1 -1
  309. package/src/features/facets/InteractionsFacetsNav.tsx +121 -0
  310. package/src/features/facets/PromptsFacetsNav.tsx +110 -0
  311. package/src/features/facets/RunsFacetsNav.tsx +40 -9
  312. package/src/features/facets/WorkflowExecutionsFacetsNav.tsx +10 -8
  313. package/src/features/facets/index.ts +11 -9
  314. package/src/features/facets/utils/SearchInterface.tsx +12 -0
  315. package/src/features/facets/{VTypeFacet.tsx → utils/VTypeFacet.tsx} +12 -5
  316. package/src/features/facets/{VUserFacet.tsx → utils/VUserFacet.tsx} +1 -1
  317. package/src/features/layout/GenericPageNavHeader.tsx +73 -10
  318. package/src/features/store/collections/BrowseCollectionView.tsx +4 -0
  319. package/src/features/store/collections/CreateCollection.tsx +3 -4
  320. package/src/features/store/collections/EditCollectionView.tsx +104 -85
  321. package/src/features/store/collections/SelectCollection.tsx +214 -29
  322. package/src/features/store/objects/DocumentSearchResults.tsx +98 -27
  323. package/src/features/store/objects/DocumentTable.tsx +14 -4
  324. package/src/features/store/objects/components/ContentOverview.tsx +536 -267
  325. package/src/features/store/objects/components/DocumentIcon.tsx +42 -13
  326. package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +12 -2
  327. package/src/features/store/objects/layout/DocumentTableColumn.tsx +16 -1
  328. package/src/features/store/objects/layout/documentLayout.tsx +10 -12
  329. package/src/features/store/objects/layout/knowledge.md +10 -10
  330. package/src/features/store/objects/layout/renderers.tsx +39 -18
  331. package/src/features/store/objects/search/DocumentSearchContext.ts +6 -1
  332. package/src/features/store/objects/search/DocumentSearchProvider.tsx +1 -1
  333. package/src/features/store/objects/selection/ObjectsActionContext.tsx +3 -2
  334. package/src/features/store/objects/selection/SelectionActions.tsx +2 -0
  335. package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +23 -10
  336. package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +22 -2
  337. package/src/features/store/objects/upload/DocumentUploadModal.tsx +23 -15
  338. package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +10 -7
  339. package/src/features/store/types/CreateOrUpdateTypeModal.tsx +1 -1
  340. package/src/features/store/types/ObjectSchemaEditor.tsx +1 -1
  341. package/src/features/user/UserInfo.tsx +66 -3
  342. package/src/router/HistoryNavigator.ts +33 -2
  343. package/src/router/Nav.tsx +4 -3
  344. package/src/shell/login/UserInfo.tsx +1 -1
  345. package/src/widgets/form/Form.tsx +19 -43
  346. package/src/widgets/form/FormContext.ts +5 -2
  347. package/src/widgets/form/fields.tsx +8 -6
  348. package/src/widgets/form/inputs.tsx +1 -0
  349. package/src/widgets/schema-editor/index.ts +0 -1
  350. package/lib/esm/core/components/Textarea.js +0 -15
  351. package/lib/esm/core/components/Textarea.js.map +0 -1
  352. package/lib/esm/features/facets/FacetsNav.js +0 -8
  353. package/lib/esm/features/facets/FacetsNav.js.map +0 -1
  354. package/lib/esm/features/facets/StringFacet.js.map +0 -1
  355. package/lib/esm/features/facets/StringListFacet.js.map +0 -1
  356. package/lib/esm/features/facets/TypeFacet.js.map +0 -1
  357. package/lib/esm/features/facets/VEnvironmentFacet.js.map +0 -1
  358. package/lib/esm/features/facets/VFacetsNav.js +0 -48
  359. package/lib/esm/features/facets/VFacetsNav.js.map +0 -1
  360. package/lib/esm/features/facets/VInteractionFacet.js.map +0 -1
  361. package/lib/esm/features/facets/VStringFacet.js.map +0 -1
  362. package/lib/esm/features/facets/VTypeFacet.js.map +0 -1
  363. package/lib/esm/features/facets/VUserFacet.js.map +0 -1
  364. package/lib/esm/features/facets/utils.js.map +0 -1
  365. package/lib/esm/widgets/schema-editor/JSONSchemaEditorModal.js +0 -49
  366. package/lib/esm/widgets/schema-editor/JSONSchemaEditorModal.js.map +0 -1
  367. package/lib/types/core/components/Textarea.d.ts +0 -8
  368. package/lib/types/core/components/Textarea.d.ts.map +0 -1
  369. package/lib/types/features/facets/FacetsNav.d.ts +0 -7
  370. package/lib/types/features/facets/FacetsNav.d.ts.map +0 -1
  371. package/lib/types/features/facets/StringFacet.d.ts.map +0 -1
  372. package/lib/types/features/facets/StringListFacet.d.ts.map +0 -1
  373. package/lib/types/features/facets/TypeFacet.d.ts.map +0 -1
  374. package/lib/types/features/facets/VEnvironmentFacet.d.ts.map +0 -1
  375. package/lib/types/features/facets/VFacetsNav.d.ts +0 -16
  376. package/lib/types/features/facets/VFacetsNav.d.ts.map +0 -1
  377. package/lib/types/features/facets/VInteractionFacet.d.ts.map +0 -1
  378. package/lib/types/features/facets/VStringFacet.d.ts.map +0 -1
  379. package/lib/types/features/facets/VTypeFacet.d.ts.map +0 -1
  380. package/lib/types/features/facets/VUserFacet.d.ts.map +0 -1
  381. package/lib/types/features/facets/utils.d.ts.map +0 -1
  382. package/lib/types/widgets/schema-editor/JSONSchemaEditorModal.d.ts +0 -10
  383. package/lib/types/widgets/schema-editor/JSONSchemaEditorModal.d.ts.map +0 -1
  384. package/src/core/components/Textarea.tsx +0 -25
  385. package/src/features/facets/FacetsNav.tsx +0 -19
  386. package/src/features/facets/VFacetsNav.tsx +0 -81
  387. package/src/widgets/schema-editor/JSONSchemaEditorModal.tsx +0 -67
  388. /package/lib/esm/features/facets/{StringFacet.js → utils/StringFacet.js} +0 -0
  389. /package/lib/esm/features/facets/{StringListFacet.js → utils/StringListFacet.js} +0 -0
  390. /package/lib/esm/features/facets/{TypeFacet.js → utils/TypeFacet.js} +0 -0
  391. /package/lib/esm/features/facets/{VEnvironmentFacet.js → utils/VEnvironmentFacet.js} +0 -0
  392. /package/lib/esm/features/facets/{VInteractionFacet.js → utils/VInteractionFacet.js} +0 -0
  393. /package/lib/esm/features/facets/{VStringFacet.js → utils/VStringFacet.js} +0 -0
  394. /package/lib/esm/features/facets/{utils.js → utils/utils.js} +0 -0
  395. /package/lib/types/features/facets/{StringFacet.d.ts → utils/StringFacet.d.ts} +0 -0
  396. /package/lib/types/features/facets/{StringListFacet.d.ts → utils/StringListFacet.d.ts} +0 -0
  397. /package/lib/types/features/facets/{TypeFacet.d.ts → utils/TypeFacet.d.ts} +0 -0
  398. /package/lib/types/features/facets/{VEnvironmentFacet.d.ts → utils/VEnvironmentFacet.d.ts} +0 -0
  399. /package/lib/types/features/facets/{VInteractionFacet.d.ts → utils/VInteractionFacet.d.ts} +0 -0
  400. /package/lib/types/features/facets/{VStringFacet.d.ts → utils/VStringFacet.d.ts} +0 -0
  401. /package/lib/types/features/facets/{VUserFacet.d.ts → utils/VUserFacet.d.ts} +0 -0
  402. /package/lib/types/features/facets/{utils.d.ts → utils/utils.d.ts} +0 -0
  403. /package/src/features/facets/{StringFacet.tsx → utils/StringFacet.tsx} +0 -0
  404. /package/src/features/facets/{StringListFacet.tsx → utils/StringListFacet.tsx} +0 -0
  405. /package/src/features/facets/{TypeFacet.tsx → utils/TypeFacet.tsx} +0 -0
  406. /package/src/features/facets/{VEnvironmentFacet.tsx → utils/VEnvironmentFacet.tsx} +0 -0
  407. /package/src/features/facets/{VInteractionFacet.tsx → utils/VInteractionFacet.tsx} +0 -0
  408. /package/src/features/facets/{VStringFacet.tsx → utils/VStringFacet.tsx} +0 -0
  409. /package/src/features/facets/{utils.tsx → utils/utils.tsx} +0 -0
@@ -1,13 +1,22 @@
1
- import { useEffect, useState } from "react";
1
+ import { useEffect, useState, memo } from "react";
2
2
 
3
3
  import { useUserSession } from "@vertesia/ui/session";
4
- import { Button, Spinner, useToast } from "@vertesia/ui/core";
4
+ import { Button, ResizableHandle, ResizablePanel, ResizablePanelGroup, Spinner, useToast } from "@vertesia/ui/core";
5
5
  import { JSONDisplay, MarkdownRenderer } from "@vertesia/ui/widgets";
6
- import { ContentObject, ImageRenditionFormat } from "@vertesia/common";
7
- import { Copy, Download, SquarePen } from "lucide-react";
6
+ import { ContentNature, ContentObject, ImageRenditionFormat, VideoMetadata, POSTER_RENDITION_NAME } from "@vertesia/common";
7
+ import { Copy, Download, SquarePen, AlertTriangle } from "lucide-react";
8
8
  import { PropertiesEditorModal } from "./PropertiesEditorModal";
9
9
  import { NavLink } from "@vertesia/ui/router";
10
10
 
11
+ // Maximum text size before cropping (128K characters)
12
+ const MAX_TEXT_DISPLAY_SIZE = 128 * 1024;
13
+
14
+ enum PanelView {
15
+ Text = "text",
16
+ Image = "image",
17
+ Video = "video"
18
+ }
19
+
11
20
  interface ContentOverviewProps {
12
21
  object: ContentObject;
13
22
  loadText?: boolean;
@@ -18,15 +27,51 @@ export function ContentOverview({
18
27
  loadText,
19
28
  refetch,
20
29
  }: ContentOverviewProps) {
21
- const { client, store } = useUserSession();
22
- const [isLoadingText, setIsLoadingText] = useState(false);
23
- const [text, setText] = useState<string | undefined>(object.text);
24
- const [imageUrl, setImageUrl] = useState<string>();
25
- const [isPropertiesModalOpen, setPropertiesModalOpen] = useState(false);
26
30
  const toast = useToast();
31
+
32
+ const handleCopyContent = async (
33
+ content: string,
34
+ type: "text" | "properties",
35
+ ) => {
36
+ try {
37
+ await navigator.clipboard.writeText(content);
38
+ toast({
39
+ status: "success",
40
+ title: `${type === "text" ? "Content" : "Properties"} copied`,
41
+ description: `Successfully copied ${type} to clipboard`,
42
+ duration: 2000,
43
+ });
44
+ } catch (err) {
45
+ console.error(`Failed to copy ${type}:`, err);
46
+ toast({
47
+ status: "error",
48
+ title: "Copy failed",
49
+ description: `Failed to copy ${type} to clipboard`,
50
+ duration: 5000,
51
+ });
52
+ }
53
+ };
54
+
55
+ return (
56
+ <>
57
+ <ResizablePanelGroup direction="horizontal" className="h-[calc(100vh-200px)]">
58
+ <ResizablePanel className="min-w-[100px]">
59
+ <PropertiesPanel object={object} refetch={refetch ?? (() => Promise.resolve())} handleCopyContent={handleCopyContent} />
60
+ </ResizablePanel>
61
+ <ResizableHandle withHandle />
62
+
63
+ <ResizablePanel className="min-w-[100px]">
64
+ <DataPanel object={object} loadText={loadText ?? false} handleCopyContent={handleCopyContent} />
65
+ </ResizablePanel>
66
+ </ResizablePanelGroup>
67
+
68
+ </>
69
+ );
70
+ }
71
+
72
+ function PropertiesPanel({ object, refetch, handleCopyContent }: { object: ContentObject, refetch: () => Promise<unknown>, handleCopyContent: (content: string, type: "text" | "properties") => Promise<void> }) {
27
73
  const [viewCode, setViewCode] = useState(false);
28
- const VIEW_JSON = "JSON";
29
- const VIEW_TEXT = "Preview";
74
+ const [isPropertiesModalOpen, setPropertiesModalOpen] = useState(false);
30
75
 
31
76
  const handleOpenPropertiesModal = () => {
32
77
  setPropertiesModalOpen(true);
@@ -36,13 +81,119 @@ export function ContentOverview({
36
81
  setPropertiesModalOpen(false);
37
82
  };
38
83
 
84
+ return (
85
+ <>
86
+ <div className="flex justify-between items-center px-2">
87
+ <div className="flex items-center gap-1 bg-muted mb-2 p-1 rounded">
88
+ <Button
89
+ variant={`${viewCode ? "ghost" : "primary"}`}
90
+ size="sm"
91
+ alt="Preview properties"
92
+ onClick={() => setViewCode(!viewCode)}
93
+ >
94
+ Properties
95
+ </Button>
96
+ <Button
97
+ variant={`${viewCode ? "primary" : "ghost"}`}
98
+ size="sm"
99
+ alt="View in JSON format"
100
+ onClick={() => setViewCode(!viewCode)}
101
+ >
102
+ JSON
103
+ </Button>
104
+ </div>
105
+ <div className="flex items-center gap-2">
106
+ {object.properties && (
107
+ <Button
108
+ variant="ghost"
109
+ size="sm"
110
+ title="Copy properties"
111
+ onClick={() =>
112
+ handleCopyContent(
113
+ JSON.stringify(
114
+ object.properties,
115
+ null,
116
+ 2,
117
+ ),
118
+ "properties",
119
+ )
120
+ }
121
+ >
122
+ <Copy className="size-4" />
123
+ </Button>
124
+ )}
125
+ <Button
126
+ variant="ghost"
127
+ size="sm"
128
+ onClick={handleOpenPropertiesModal}
129
+ title="Edit properties"
130
+ className="flex items-center gap-2"
131
+ >
132
+ <SquarePen className="size-4" />
133
+ </Button>
134
+ </div>
135
+ </div>
136
+
137
+ {
138
+ object.properties ? (
139
+ <div className="h-[calc(100vh-220px)] overflow-auto px-2">
140
+ <JSONDisplay
141
+ value={object.properties}
142
+ viewCode={viewCode}
143
+
144
+ />
145
+ </div>
146
+ ) : (
147
+ <div className="h-[calc(100vh-220px)] overflow-auto px-2">
148
+ <div>No properties defined</div>
149
+ </div>
150
+ )
151
+ }
152
+ {/* Properties Editor Modal */}
153
+ <PropertiesEditorModal
154
+ isOpen={isPropertiesModalOpen}
155
+ onClose={handleClosePropertiesModal}
156
+ object={object}
157
+ refetch={refetch}
158
+ />
159
+ </>
160
+ );
161
+ }
162
+
163
+ function DataPanel({ object, loadText, handleCopyContent }: { object: ContentObject, loadText: boolean, handleCopyContent: (content: string, type: "text" | "properties") => Promise<void> }) {
164
+ const { store } = useUserSession();
165
+
166
+ const isImage = object?.metadata?.type === ContentNature.Image;
167
+ const isVideo = object?.metadata?.type === ContentNature.Video;
168
+
169
+ // Determine initial panel view
170
+ const getInitialView = (): PanelView => {
171
+ if (isVideo) return PanelView.Video;
172
+ if (isImage) return PanelView.Image;
173
+ return PanelView.Text;
174
+ };
175
+
176
+ const [currentPanel, setCurrentPanel] = useState<PanelView>(getInitialView());
177
+
178
+ const [text, setText] = useState<string | undefined>(object.text);
179
+ const [isLoadingText, setIsLoadingText] = useState<boolean>(false);
180
+ const [isTextCropped, setIsTextCropped] = useState<boolean>(false);
181
+
39
182
  useEffect(() => {
40
183
  if (loadText && !text) {
41
184
  setIsLoadingText(true);
42
185
  store.objects
43
186
  .getObjectText(object.id)
44
187
  .then((res) => {
45
- setText(res.text);
188
+ if (res.text.length > MAX_TEXT_DISPLAY_SIZE) {
189
+ // Crop the text to 128K characters
190
+ const croppedText = res.text.substring(0, MAX_TEXT_DISPLAY_SIZE);
191
+ setText(croppedText);
192
+ setIsTextCropped(true);
193
+ } else {
194
+ setText(res.text);
195
+ setIsTextCropped(false);
196
+ }
46
197
  })
47
198
  .catch((err) => {
48
199
  console.error("Failed to load text", err);
@@ -53,30 +204,87 @@ export function ContentOverview({
53
204
  }
54
205
  }, [loadText]);
55
206
 
56
- const handleCopyContent = async (
57
- content: string,
58
- type: "text" | "properties",
59
- ) => {
60
- try {
61
- await navigator.clipboard.writeText(content);
62
- toast({
63
- status: "success",
64
- title: `${type === "text" ? "Content" : "Properties"} copied`,
65
- description: `Successfully copied ${type} to clipboard`,
66
- duration: 2000,
67
- });
68
- } catch (err) {
69
- console.error(`Failed to copy ${type}:`, err);
70
- toast({
71
- status: "error",
72
- title: "Copy failed",
73
- description: `Failed to copy ${type} to clipboard`,
74
- duration: 5000,
75
- });
76
- }
77
- };
207
+ return (
208
+ <>
209
+ <div className="flex justify-between items-center px-2">
210
+ <div className="flex items-center gap-1 bg-muted mb-2 p-1 rounded">
211
+ {isImage &&
212
+ <Button
213
+ variant={currentPanel === PanelView.Image ? "primary" : "ghost"}
214
+ size="sm"
215
+ alt="View Image"
216
+ onClick={() => setCurrentPanel(PanelView.Image)}
217
+ >
218
+ Image
219
+ </Button>
220
+ }
221
+ {isVideo &&
222
+ <Button
223
+ variant={currentPanel === PanelView.Video ? "primary" : "ghost"}
224
+ size="sm"
225
+ alt="View Video"
226
+ onClick={() => setCurrentPanel(PanelView.Video)}
227
+ >
228
+ Video
229
+ </Button>
230
+ }
231
+ <Button
232
+ variant={currentPanel === PanelView.Text ? "primary" : "ghost"}
233
+ size="sm"
234
+ alt="View Text"
235
+ onClick={() => setCurrentPanel(PanelView.Text)}
236
+ >
237
+ Text
238
+ </Button>
239
+
240
+ </div>
241
+ {currentPanel === PanelView.Text && <TextActions object={object} text={text} handleCopyContent={handleCopyContent} />}
242
+ </div>
243
+ {
244
+ currentPanel === PanelView.Image ? (
245
+ <ImagePanel object={object} />
246
+ ) : currentPanel === PanelView.Video ? (
247
+ <VideoPanel object={object} />
248
+ ) : (
249
+ isLoadingText ? (
250
+ <div className="flex justify-center items-center h-[calc(100vh-260px)]">
251
+ <Spinner size="lg" />
252
+ </div>
253
+ ) : (
254
+ <TextPanel object={object} text={text} isTextCropped={isTextCropped} />
255
+ )
256
+ )
257
+ }
258
+ </>
259
+ );
260
+ }
261
+
262
+ function TextActions({ object, text, handleCopyContent }: { object: ContentObject, handleCopyContent: (content: string, type: "text" | "properties") => Promise<void>, text: string | undefined }) {
263
+ const { client } = useUserSession();
264
+ const toast = useToast();
265
+ const [loadingFormat, setLoadingFormat] = useState<"docx" | "pdf" | null>(null);
266
+
267
+ const content = object.content;
268
+
269
+ const isMarkdown =
270
+ content &&
271
+ content.type &&
272
+ content.type === "text/markdown";
78
273
 
79
274
  const handleExportDocument = async (format: "docx" | "pdf") => {
275
+ // Prevent multiple concurrent exports
276
+ if (loadingFormat) return;
277
+
278
+ setLoadingFormat(format);
279
+
280
+ // Show immediate feedback
281
+ toast({
282
+ status: "info",
283
+ title: `Preparing ${format.toUpperCase()}`,
284
+ description: "Fetching your document...",
285
+ duration: 2000,
286
+ });
287
+
80
288
  try {
81
289
  // Request document rendition from the server
82
290
  const response = await client.objects.getRendition(object.id, {
@@ -140,262 +348,323 @@ export function ContentOverview({
140
348
  description: `Failed to export document to ${format.toUpperCase()} format`,
141
349
  duration: 5000,
142
350
  });
351
+ } finally {
352
+ setLoadingFormat(null);
143
353
  }
144
354
  };
145
355
 
146
356
  const handleExportDocx = () => handleExportDocument("docx");
147
357
  const handleExportPdf = () => handleExportDocument("pdf");
358
+ return (
359
+ <div className="h-[41px] text-lg font-semibold flex justify-between items-center px-2">
360
+ <div className="flex items-center gap-2">
361
+ {text && (
362
+ <Button variant="ghost" size="sm" title="Copy text" className="flex items-center gap-2" onClick={() => handleCopyContent(text, "text")}>
363
+ <Copy className="size-4" />
364
+ </Button>
365
+ )}
366
+ {isMarkdown && text && (
367
+ <>
368
+ <Button
369
+ variant="ghost"
370
+ size="sm"
371
+ onClick={handleExportDocx}
372
+ disabled={loadingFormat !== null}
373
+ className="flex items-center gap-2"
374
+ >
375
+ {loadingFormat === "docx" ? (
376
+ <Spinner size="sm" />
377
+ ) : (
378
+ <Download className="size-4" />
379
+ )}
380
+ DOCX
381
+ </Button>
382
+ <Button
383
+ variant="ghost"
384
+ size="sm"
385
+ onClick={handleExportPdf}
386
+ disabled={loadingFormat !== null}
387
+ className="flex items-center gap-2"
388
+ >
389
+ {loadingFormat === "pdf" ? (
390
+ <Spinner size="sm" />
391
+ ) : (
392
+ <Download className="size-4" />
393
+ )}
394
+ PDF
395
+ </Button>
396
+ </>
397
+ )}
398
+ </div>
399
+ </div>
400
+ );
401
+ }
148
402
 
403
+ const TextPanel = memo(({ object, text, isTextCropped }: { object: ContentObject, text: string | undefined, isTextCropped: boolean }) => {
149
404
  const content = object.content;
150
- const isImage =
151
- content &&
152
- content.source &&
153
- content.type &&
154
- content.type.startsWith("image/");
405
+
406
+ // Check if content type is markdown or plain text
155
407
  const isMarkdownOrText =
156
408
  content &&
157
409
  content.type &&
158
410
  (content.type === "text/markdown" || content.type === "text/plain");
159
- // Check for markdown indicators, ignoring any HTML comments
160
- const seemsMarkdown =
161
- text &&
162
- // Look for markdown indicators
163
- (text.includes("\n#") ||
164
- text.includes("\n*") ||
165
- text.includes("\n+") ||
166
- text.includes("!["));
167
411
 
168
- useEffect(() => {
169
- if (isImage) {
170
- client.objects
171
- .getRendition(object.id, {
172
- format: ImageRenditionFormat.jpeg,
173
- generate_if_missing: false,
174
- sign_url: true,
175
- })
176
- .then((r) => {
177
- if (r.status === "found") {
178
- return r.renditions?.length ? r.renditions[0] : null;
179
- } else {
180
- return object;
181
- }
182
- })
183
- .catch(() => {
184
- return object;
185
- })
186
- .then(() => {
187
- client.files
188
- .getDownloadUrl(object.content.source!)
189
- .then((r) => {
190
- setImageUrl(r.url);
191
- });
192
- });
193
- }
194
- }, []);
412
+ // Check if text content looks like markdown
413
+ const seemsMarkdown = text && (
414
+ text.includes("\n# ") ||
415
+ text.includes("\n## ") ||
416
+ text.includes("\n### ") ||
417
+ text.includes("\n* ") ||
418
+ text.includes("\n- ") ||
419
+ text.includes("\n+ ") ||
420
+ text.includes("![") ||
421
+ text.includes("](")
422
+ );
195
423
 
196
- return (
197
- <div className="w-full">
198
- <div className="flex flex-col lg:flex-row lg:gap-8">
199
- <div className="w-full lg:w-1/2">
200
- <div className="h-[41px] text-lg font-semibold mb-4 border-b flex justify-between items-center">
201
- <div className="flex items-center gap-1">
202
- Properties
203
- <Button
204
- variant="outline"
205
- size="sm"
206
- alt={`${viewCode ? "Preview" : "View in JSON format"}`}
207
- onClick={() => setViewCode(!viewCode)}
208
- >
209
- {viewCode ? VIEW_TEXT : VIEW_JSON}
210
- </Button>
211
- </div>
212
- <div className="flex items-center gap-2">
213
- {object.properties && (
214
- <Button
215
- variant="ghost"
216
- size="sm"
217
- title="Copy properties"
218
- onClick={() =>
219
- handleCopyContent(
220
- JSON.stringify(
221
- object.properties,
222
- null,
223
- 2,
224
- ),
225
- "properties",
226
- )
227
- }
228
- >
229
- <Copy className="size-4" />
230
- </Button>
231
- )}
232
- <Button
233
- variant="ghost"
234
- size="sm"
235
- onClick={handleOpenPropertiesModal}
236
- title="Edit properties"
237
- className="flex items-center gap-2"
238
- >
239
- <SquarePen className="size-4" />
240
- </Button>
241
- </div>
242
- </div>
243
- {object.properties ? (
244
- <JSONDisplay
245
- value={object.properties}
246
- viewCode={viewCode}
247
- />
248
- ) : (
249
- <div>No properties defined</div>
250
- )}
251
- {isImage && (
252
- <div className="my-4">
253
- <div className="h-[41px] text-lg font-semibold mb-4 border-b flex justify-between items-center">
254
- <span className="py-1">Image</span>
255
- </div>
256
- {imageUrl ? (
257
- <img
258
- src={imageUrl}
259
- alt={object.name}
260
- className="w-full object-contain"
261
- />
262
- ) : (
263
- <Spinner size="md" />
264
- )}
265
- </div>
266
- )}
267
- </div>
424
+ // Render as markdown if it's markdown/text type OR if text looks like markdown
425
+ const shouldRenderAsMarkdown = isMarkdownOrText || seemsMarkdown;
268
426
 
269
- <div className="w-full lg:w-1/2 mt-4 lg:mt-0">
270
- <div className="h-[41px] text-lg font-semibold mb-4 border-b flex justify-between items-center">
271
- <span className="py-1">Text</span>
272
- <div className="flex items-center gap-2">
273
- {text && (
274
- <Button
275
- variant="ghost"
276
- size="sm"
277
- title="Copy text"
278
- onClick={() =>
279
- handleCopyContent(text, "text")
280
- }
281
- className="flex items-center gap-2"
282
- >
283
- <Copy className="h-4 w-4" />
284
- </Button>
285
- )}
286
- {(isMarkdownOrText || seemsMarkdown) && text && (
287
- <>
288
- <Button
289
- variant="ghost"
290
- size="sm"
291
- onClick={handleExportDocx}
292
- className="flex items-center gap-2"
293
- >
294
- <Download className="h-4 w-4" />
295
- DOCX
296
- </Button>
297
- <Button
298
- variant="ghost"
299
- size="sm"
300
- onClick={handleExportPdf}
301
- className="flex items-center gap-2"
302
- >
303
- <Download className="h-4 w-4" />
304
- PDF
305
- </Button>
306
- </>
307
- )}
427
+ return (
428
+ text ? (
429
+ <>
430
+ {isTextCropped && (
431
+ <div className="px-2 py-2 bg-attention/10 border-l-4 border-attention mx-2 mb-2 rounded">
432
+ <div className="flex items-center gap-2 text-attention">
433
+ <AlertTriangle className="size-4" />
434
+ <span className="text-sm font-semibold">Showing first 128K characters only</span>
308
435
  </div>
309
436
  </div>
310
- {isLoadingText && <Spinner size="md" />}
311
- {text ? (
312
- <div className="border shadow-xs rounded-xs max-w-7xl">
313
- {seemsMarkdown ? (
314
- <div className="vprose prose-sm p-1">
315
- <MarkdownRenderer
316
- components={{
317
- a: ({ node, ...props }: { node?: any; href?: string; children?: React.ReactNode }) => {
318
- const href = props.href || "";
319
- if (href.includes("/store/objects/")) {
320
- return (
321
- <NavLink
322
- topLevelNav
323
- href={href}
324
- className="text-info"
325
- >
326
- {props.children}
327
- </NavLink>
328
- );
437
+ )}
438
+ <div className="max-w-7xl px-2 h-[calc(100vh-210px)] overflow-auto">
439
+ {shouldRenderAsMarkdown ? (
440
+ <div className="vprose prose-sm p-1">
441
+ <MarkdownRenderer
442
+ components={{
443
+ a: ({ node, ...props }: { node?: any; href?: string; children?: React.ReactNode }) => {
444
+ const href = props.href || "";
445
+ if (href.includes("/store/objects/")) {
446
+ return (
447
+ <NavLink
448
+ topLevelNav
449
+ href={href}
450
+ className="text-info"
451
+ >
452
+ {props.children}
453
+ </NavLink>
454
+ );
455
+ }
456
+ return <a {...props} data-debug="test" target="_blank" rel="noopener noreferrer" />;
457
+ },
458
+ p: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
459
+ <p {...props} className={`my-0`} />
460
+ ),
461
+ pre: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
462
+ <pre {...props} className={`my-2 p-2 rounded`} />
463
+ ),
464
+ code: ({
465
+ node,
466
+ className,
467
+ children,
468
+ ...props
469
+ }: {
470
+ node?: any;
471
+ className?: string;
472
+ children?: React.ReactNode;
473
+ }) => {
474
+ const match = /language-(\w+)/.exec(className || "");
475
+ const isInline = !match;
476
+ return (
477
+ <code
478
+ {...props}
479
+ className={
480
+ isInline
481
+ ? `px-1.5 py-0.5 rounded`
482
+ : "text-muted"
329
483
  }
330
- return <a {...props} data-debug="test" target="_blank" rel="noopener noreferrer" />;
331
- },
332
- p: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
333
- <p {...props} className={`my-0`} />
334
- ),
335
- pre: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
336
- <pre {...props} className={`my-2 p-2 rounded`} />
337
- ),
338
- code: ({
339
- node,
340
- className,
341
- children,
342
- ...props
343
- }: {
344
- node?: any;
345
- className?: string;
346
- children?: React.ReactNode;
347
- }) => {
348
- const match = /language-(\w+)/.exec(className || "");
349
- const isInline = !match;
350
- return (
351
- <code
352
- {...props}
353
- className={
354
- isInline
355
- ? `px-1.5 py-0.5 rounded`
356
- : "text-muted"
357
- }
358
- >
359
- {children}
360
- </code>
361
- );
362
- },
363
- h1: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
364
- <h1 {...props} className={`font-bold text-2xl my-2`} />
365
- ),
366
- h2: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
367
- <h2 {...props} className={`font-bold text-xl my-2`} />
368
- ),
369
- h3: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
370
- <h3 {...props} className={`font-bold text-lg my-2`} />
371
- ),
372
- li: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
373
- <li {...props} />
374
- ),
375
- }}
376
- >
377
- {text}
378
- </MarkdownRenderer>
379
- </div>
380
- ) : (
381
- <pre className="text-wrap bg-muted text-muted p-2">
382
- {text}
383
- </pre>
384
- )}
484
+ >
485
+ {children}
486
+ </code>
487
+ );
488
+ },
489
+ h1: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
490
+ <h1 {...props} className={`font-bold text-2xl my-2`} />
491
+ ),
492
+ h2: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
493
+ <h2 {...props} className={`font-bold text-xl my-2`} />
494
+ ),
495
+ h3: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
496
+ <h3 {...props} className={`font-bold text-lg my-2`} />
497
+ ),
498
+ li: ({ node, ...props }: { node?: any; children?: React.ReactNode }) => (
499
+ <li {...props} />
500
+ ),
501
+ }}
502
+ >
503
+ {text}
504
+ </MarkdownRenderer>
385
505
  </div>
386
506
  ) : (
387
- <div>No content</div>
507
+ <pre className="text-wrap bg-muted text-muted p-2">
508
+ {text}
509
+ </pre>
388
510
  )}
389
511
  </div>
512
+ </>
513
+ ) :
514
+ <div className="px-2">
515
+ <div>No content</div>
390
516
  </div>
517
+ );
518
+ });
391
519
 
392
- {/* Properties Editor Modal */}
393
- <PropertiesEditorModal
394
- isOpen={isPropertiesModalOpen}
395
- onClose={handleClosePropertiesModal}
396
- object={object}
397
- refetch={refetch}
398
- />
520
+ function ImagePanel({ object }: { object: ContentObject }) {
521
+ const { client } = useUserSession();
522
+ const [imageUrl, setImageUrl] = useState<string>();
523
+
524
+ const content = object.content;
525
+ const isImage = object.metadata && object.metadata.type === ContentNature.Image;
526
+
527
+ useEffect(() => {
528
+ if (isImage) {
529
+ const loadImage = async () => {
530
+ const webSupportedFormats = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'];
531
+ const isOriginalWebSupported = content?.type && webSupportedFormats.includes(content.type);
532
+
533
+ try {
534
+ const rendition = await client.objects.getRendition(object.id, {
535
+ format: ImageRenditionFormat.jpeg,
536
+ generate_if_missing: false,
537
+ sign_url: true,
538
+ });
539
+
540
+ if (rendition.status === "found" && rendition.renditions?.length) {
541
+ // Use rendition URL directly
542
+ setImageUrl(rendition.renditions[0]);
543
+ } else if (isOriginalWebSupported) {
544
+ // Fall back to original file only if web-supported
545
+ const downloadUrl = await client.files.getDownloadUrl(object.content.source!);
546
+ setImageUrl(downloadUrl.url);
547
+ }
548
+ } catch (error) {
549
+ // Fall back to original file only if web-supported
550
+ if (isOriginalWebSupported) {
551
+ const downloadUrl = await client.files.getDownloadUrl(object.content.source!);
552
+ setImageUrl(downloadUrl.url);
553
+ }
554
+ }
555
+ };
556
+
557
+ loadImage();
558
+ }
559
+ }, []);
560
+
561
+ return (
562
+ <div className="mb-4 px-2">
563
+ {imageUrl ? (
564
+ <img
565
+ src={imageUrl}
566
+ alt={object.name}
567
+ className="w-full object-contain"
568
+ />
569
+ ) : (
570
+ <Spinner size="md" />
571
+ )}
399
572
  </div>
400
573
  );
401
574
  }
575
+
576
+ function VideoPanel({ object }: { object: ContentObject }) {
577
+ const { client } = useUserSession();
578
+ const [videoUrl, setVideoUrl] = useState<string>();
579
+ const [posterUrl, setPosterUrl] = useState<string>();
580
+ const [isLoading, setIsLoading] = useState<boolean>(true);
581
+
582
+ const content = object.content;
583
+ const isVideo = object.metadata?.type === ContentNature.Video;
584
+
585
+ // Check if there are mp4 or webm renditions available in metadata
586
+ const metadata = object.metadata as VideoMetadata;
587
+ const renditions = metadata?.renditions || [];
588
+
589
+ // Find mp4 or webm rendition by mime type, preferring mp4
590
+ const webRendition = renditions.find(r => r.content.type === 'video/mp4') ||
591
+ renditions.find(r => r.content.type === 'video/webm');
592
+
593
+ // Check if original file is web-compatible
594
+ const webSupportedFormats = ['video/mp4', 'video/webm'];
595
+ const isOriginalWebSupported = content?.type && webSupportedFormats.includes(content.type);
596
+
597
+ // Get poster
598
+ const poster = renditions.find(r => r.name === POSTER_RENDITION_NAME);
599
+
600
+ useEffect(() => {
601
+ const loadPoster = async () => {
602
+ if (poster?.content?.source) {
603
+ try {
604
+ const response = await client.files.getDownloadUrl(poster.content.source);
605
+ setPosterUrl(response.url);
606
+ } catch (error) {
607
+ console.error("Failed to load poster image", error);
608
+ }
609
+ }
610
+ };
611
+ loadPoster();
612
+ }, [poster, client]);
613
+
614
+ useEffect(() => {
615
+ if (isVideo && (webRendition?.content?.source || isOriginalWebSupported)) {
616
+ const loadVideoUrl = async () => {
617
+ try {
618
+ let downloadUrl;
619
+ if (webRendition?.content?.source) {
620
+ // Use rendition if available
621
+ downloadUrl = await client.files.getDownloadUrl(webRendition.content.source);
622
+ } else if (isOriginalWebSupported && content?.source) {
623
+ // Fall back to original file if web-supported
624
+ downloadUrl = await client.files.getDownloadUrl(content.source);
625
+ }
626
+ if (downloadUrl) {
627
+ setVideoUrl(downloadUrl.url);
628
+ }
629
+ } catch (error) {
630
+ console.error("Failed to get video URL", error);
631
+ } finally {
632
+ setIsLoading(false);
633
+ }
634
+ };
635
+ loadVideoUrl();
636
+ } else {
637
+ setIsLoading(false);
638
+ }
639
+ }, [isVideo, webRendition, isOriginalWebSupported, content?.source, client]);
640
+
641
+ return (
642
+ <div className="mb-4 px-2">
643
+ {!webRendition && !isOriginalWebSupported ? (
644
+ <div className="flex justify-center items-center h-[400px] text-muted">
645
+ <div className="text-center">
646
+ <p>No web-compatible video rendition available</p>
647
+ <p className="text-sm mt-2">MP4 or WebM format required</p>
648
+ </div>
649
+ </div>
650
+ ) : isLoading ? (
651
+ <div className="flex justify-center items-center h-[400px]">
652
+ <Spinner size="md" />
653
+ </div>
654
+ ) : videoUrl ? (
655
+ <video
656
+ src={videoUrl}
657
+ poster={posterUrl}
658
+ controls
659
+ className="w-full max-h-[calc(100vh-260px)] object-contain"
660
+ >
661
+ Your browser does not support the video tag.
662
+ </video>
663
+ ) : (
664
+ <div className="flex justify-center items-center h-[400px] text-muted">
665
+ Failed to load video
666
+ </div>
667
+ )}
668
+ </div>
669
+ );
670
+ }