@vertesia/ui 0.79.0 → 0.79.2

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 (307) 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/SidePanel.js +2 -2
  6. package/lib/esm/core/components/SidePanel.js.map +1 -1
  7. package/lib/esm/core/components/TagsInput.js +194 -0
  8. package/lib/esm/core/components/TagsInput.js.map +1 -0
  9. package/lib/esm/core/components/index.js +2 -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 +2 -2
  16. package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
  17. package/lib/esm/core/components/shadcn/index.js +1 -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/popover.js +1 -1
  22. package/lib/esm/core/components/shadcn/popover.js.map +1 -1
  23. package/lib/esm/core/components/shadcn/resizeable.js +2 -2
  24. package/lib/esm/core/components/shadcn/resizeable.js.map +1 -1
  25. package/lib/esm/core/components/shadcn/selectBox.js +15 -9
  26. package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
  27. package/lib/esm/core/components/shadcn/tabs.js +10 -3
  28. package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
  29. package/lib/esm/core/components/shadcn/textarea.js +7 -0
  30. package/lib/esm/core/components/shadcn/textarea.js.map +1 -0
  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 +2 -2
  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 +19 -0
  56. package/lib/esm/features/facets/CollectionsFacetsNav.js.map +1 -1
  57. package/lib/esm/features/facets/InteractionsFacetsNav.js +9 -3
  58. package/lib/esm/features/facets/InteractionsFacetsNav.js.map +1 -1
  59. package/lib/esm/features/facets/utils/VTypeFacet.js +4 -1
  60. package/lib/esm/features/facets/utils/VTypeFacet.js.map +1 -1
  61. package/lib/esm/features/layout/GenericPageNavHeader.js +58 -5
  62. package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -1
  63. package/lib/esm/features/store/collections/BrowseCollectionView.js +3 -0
  64. package/lib/esm/features/store/collections/BrowseCollectionView.js.map +1 -1
  65. package/lib/esm/features/store/collections/CreateCollection.js +2 -2
  66. package/lib/esm/features/store/collections/CreateCollection.js.map +1 -1
  67. package/lib/esm/features/store/collections/EditCollectionView.js +39 -29
  68. package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
  69. package/lib/esm/features/store/collections/SelectCollection.js +82 -16
  70. package/lib/esm/features/store/collections/SelectCollection.js.map +1 -1
  71. package/lib/esm/features/store/collections/SharedPropsEditor.js +40 -0
  72. package/lib/esm/features/store/collections/SharedPropsEditor.js.map +1 -0
  73. package/lib/esm/features/store/collections/SyncMemberHeadsToggle.js +35 -0
  74. package/lib/esm/features/store/collections/SyncMemberHeadsToggle.js.map +1 -0
  75. package/lib/esm/features/store/collections/index.js +2 -0
  76. package/lib/esm/features/store/collections/index.js.map +1 -1
  77. package/lib/esm/features/store/objects/DocumentSearchResults.js +35 -9
  78. package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
  79. package/lib/esm/features/store/objects/DocumentTable.js +6 -6
  80. package/lib/esm/features/store/objects/DocumentTable.js.map +1 -1
  81. package/lib/esm/features/store/objects/components/ContentOverview.js +158 -114
  82. package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
  83. package/lib/esm/features/store/objects/components/DocumentIcon.js +5 -3
  84. package/lib/esm/features/store/objects/components/DocumentIcon.js.map +1 -1
  85. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js +11 -2
  86. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -1
  87. package/lib/esm/features/store/objects/components/useDownloadObject.js +2 -2
  88. package/lib/esm/features/store/objects/components/useDownloadObject.js.map +1 -1
  89. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +13 -1
  90. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  91. package/lib/esm/features/store/objects/layout/documentLayout.js +5 -5
  92. package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -1
  93. package/lib/esm/features/store/objects/layout/renderers.js +28 -12
  94. package/lib/esm/features/store/objects/layout/renderers.js.map +1 -1
  95. package/lib/esm/features/store/objects/search/DocumentSearchContext.js +5 -1
  96. package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  97. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js +1 -1
  98. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js.map +1 -1
  99. package/lib/esm/features/store/objects/selection/ObjectsActionContext.js +3 -2
  100. package/lib/esm/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
  101. package/lib/esm/features/store/objects/selection/SelectionActions.js +2 -0
  102. package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
  103. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js +10 -2
  104. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js.map +1 -1
  105. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js +20 -2
  106. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
  107. package/lib/esm/features/store/objects/upload/DocumentUploadModal.js +15 -7
  108. package/lib/esm/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
  109. package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js +10 -9
  110. package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -1
  111. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js +1 -1
  112. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js.map +1 -1
  113. package/lib/esm/features/user/UserInfo.js +2 -0
  114. package/lib/esm/features/user/UserInfo.js.map +1 -1
  115. package/lib/esm/router/HistoryNavigator.js +25 -2
  116. package/lib/esm/router/HistoryNavigator.js.map +1 -1
  117. package/lib/esm/router/Nav.js +3 -3
  118. package/lib/esm/router/Nav.js.map +1 -1
  119. package/lib/esm/session/UserSession.js +1 -0
  120. package/lib/esm/session/UserSession.js.map +1 -1
  121. package/lib/esm/session/UserSessionProvider.js +9 -2
  122. package/lib/esm/session/UserSessionProvider.js.map +1 -1
  123. package/lib/esm/session/auth/composable.js +66 -67
  124. package/lib/esm/session/auth/composable.js.map +1 -1
  125. package/lib/esm/shell/apps/AppProjectSelector.js +2 -2
  126. package/lib/esm/shell/apps/AppProjectSelector.js.map +1 -1
  127. package/lib/esm/widgets/form/Form.js +17 -30
  128. package/lib/esm/widgets/form/Form.js.map +1 -1
  129. package/lib/esm/widgets/form/FormContext.js +4 -2
  130. package/lib/esm/widgets/form/FormContext.js.map +1 -1
  131. package/lib/esm/widgets/form/ManagedObject.js +4 -0
  132. package/lib/esm/widgets/form/ManagedObject.js.map +1 -1
  133. package/lib/esm/widgets/form/fields.js +4 -3
  134. package/lib/esm/widgets/form/fields.js.map +1 -1
  135. package/lib/esm/widgets/form/inputs.js +2 -0
  136. package/lib/esm/widgets/form/inputs.js.map +1 -1
  137. package/lib/tsconfig.tsbuildinfo +1 -1
  138. package/lib/types/core/components/Panel.d.ts +11 -0
  139. package/lib/types/core/components/Panel.d.ts.map +1 -0
  140. package/lib/types/core/components/SidePanel.d.ts.map +1 -1
  141. package/lib/types/core/components/TagsInput.d.ts +16 -0
  142. package/lib/types/core/components/TagsInput.d.ts.map +1 -0
  143. package/lib/types/core/components/index.d.ts +2 -1
  144. package/lib/types/core/components/index.d.ts.map +1 -1
  145. package/lib/types/core/components/shadcn/breadcrumb.d.ts +3 -2
  146. package/lib/types/core/components/shadcn/breadcrumb.d.ts.map +1 -1
  147. package/lib/types/core/components/shadcn/button.d.ts.map +1 -1
  148. package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  149. package/lib/types/core/components/shadcn/index.d.ts +1 -0
  150. package/lib/types/core/components/shadcn/index.d.ts.map +1 -1
  151. package/lib/types/core/components/shadcn/input.d.ts.map +1 -1
  152. package/lib/types/core/components/shadcn/popover.d.ts +7 -0
  153. package/lib/types/core/components/shadcn/popover.d.ts.map +1 -1
  154. package/lib/types/core/components/shadcn/selectBox.d.ts +3 -2
  155. package/lib/types/core/components/shadcn/selectBox.d.ts.map +1 -1
  156. package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
  157. package/lib/types/core/components/shadcn/textarea.d.ts +4 -0
  158. package/lib/types/core/components/shadcn/textarea.d.ts.map +1 -0
  159. package/lib/types/core/hooks/CompositeState.d.ts +115 -6
  160. package/lib/types/core/hooks/CompositeState.d.ts.map +1 -1
  161. package/lib/types/core/hooks/index.d.ts +1 -0
  162. package/lib/types/core/hooks/index.d.ts.map +1 -1
  163. package/lib/types/core/hooks/useScrollableSearch.d.ts +82 -0
  164. package/lib/types/core/hooks/useScrollableSearch.d.ts.map +1 -0
  165. package/lib/types/env/index.d.ts +3 -1
  166. package/lib/types/env/index.d.ts.map +1 -1
  167. package/lib/types/features/agent/PayloadBuilder.d.ts +11 -19
  168. package/lib/types/features/agent/PayloadBuilder.d.ts.map +1 -1
  169. package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  170. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +1 -1
  171. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  172. package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
  173. package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
  174. package/lib/types/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts.map +1 -1
  175. package/lib/types/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  176. package/lib/types/features/facets/InteractionsFacetsNav.d.ts +1 -0
  177. package/lib/types/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
  178. package/lib/types/features/facets/utils/SearchInterface.d.ts +6 -1
  179. package/lib/types/features/facets/utils/SearchInterface.d.ts.map +1 -1
  180. package/lib/types/features/facets/utils/VTypeFacet.d.ts +2 -1
  181. package/lib/types/features/facets/utils/VTypeFacet.d.ts.map +1 -1
  182. package/lib/types/features/layout/GenericPageNavHeader.d.ts +2 -1
  183. package/lib/types/features/layout/GenericPageNavHeader.d.ts.map +1 -1
  184. package/lib/types/features/store/collections/BrowseCollectionView.d.ts.map +1 -1
  185. package/lib/types/features/store/collections/CreateCollection.d.ts.map +1 -1
  186. package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
  187. package/lib/types/features/store/collections/SelectCollection.d.ts +6 -3
  188. package/lib/types/features/store/collections/SelectCollection.d.ts.map +1 -1
  189. package/lib/types/features/store/collections/SharedPropsEditor.d.ts +7 -0
  190. package/lib/types/features/store/collections/SharedPropsEditor.d.ts.map +1 -0
  191. package/lib/types/features/store/collections/SyncMemberHeadsToggle.d.ts +7 -0
  192. package/lib/types/features/store/collections/SyncMemberHeadsToggle.d.ts.map +1 -0
  193. package/lib/types/features/store/collections/index.d.ts +2 -0
  194. package/lib/types/features/store/collections/index.d.ts.map +1 -1
  195. package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  196. package/lib/types/features/store/objects/DocumentTable.d.ts +4 -0
  197. package/lib/types/features/store/objects/DocumentTable.d.ts.map +1 -1
  198. package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  199. package/lib/types/features/store/objects/components/DocumentIcon.d.ts +3 -1
  200. package/lib/types/features/store/objects/components/DocumentIcon.d.ts.map +1 -1
  201. package/lib/types/features/store/objects/components/SaveVersionConfirmModal.d.ts.map +1 -1
  202. package/lib/types/features/store/objects/components/useDownloadObject.d.ts +1 -1
  203. package/lib/types/features/store/objects/components/useDownloadObject.d.ts.map +1 -1
  204. package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts +2 -1
  205. package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  206. package/lib/types/features/store/objects/layout/documentLayout.d.ts +4 -2
  207. package/lib/types/features/store/objects/layout/documentLayout.d.ts.map +1 -1
  208. package/lib/types/features/store/objects/layout/renderers.d.ts +1 -1
  209. package/lib/types/features/store/objects/layout/renderers.d.ts.map +1 -1
  210. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +1 -0
  211. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  212. package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
  213. package/lib/types/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
  214. package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts +1 -0
  215. package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
  216. package/lib/types/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
  217. package/lib/types/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
  218. package/lib/types/features/user/UserInfo.d.ts.map +1 -1
  219. package/lib/types/router/HistoryNavigator.d.ts.map +1 -1
  220. package/lib/types/router/Nav.d.ts +2 -1
  221. package/lib/types/router/Nav.d.ts.map +1 -1
  222. package/lib/types/session/UserSession.d.ts.map +1 -1
  223. package/lib/types/session/UserSessionProvider.d.ts.map +1 -1
  224. package/lib/types/session/auth/composable.d.ts.map +1 -1
  225. package/lib/types/widgets/form/Form.d.ts +2 -1
  226. package/lib/types/widgets/form/Form.d.ts.map +1 -1
  227. package/lib/types/widgets/form/FormContext.d.ts +5 -2
  228. package/lib/types/widgets/form/FormContext.d.ts.map +1 -1
  229. package/lib/types/widgets/form/ManagedObject.d.ts.map +1 -1
  230. package/lib/types/widgets/form/fields.d.ts +2 -2
  231. package/lib/types/widgets/form/fields.d.ts.map +1 -1
  232. package/lib/types/widgets/form/inputs.d.ts.map +1 -1
  233. package/lib/vertesia-ui-core.js +1 -1
  234. package/lib/vertesia-ui-core.js.map +1 -1
  235. package/lib/vertesia-ui-env.js +1 -1
  236. package/lib/vertesia-ui-env.js.map +1 -1
  237. package/lib/vertesia-ui-features.js +1 -1
  238. package/lib/vertesia-ui-features.js.map +1 -1
  239. package/lib/vertesia-ui-router.js +1 -1
  240. package/lib/vertesia-ui-router.js.map +1 -1
  241. package/lib/vertesia-ui-session.js +1 -1
  242. package/lib/vertesia-ui-session.js.map +1 -1
  243. package/lib/vertesia-ui-shell.js +1 -1
  244. package/lib/vertesia-ui-shell.js.map +1 -1
  245. package/lib/vertesia-ui-widgets.js +1 -1
  246. package/lib/vertesia-ui-widgets.js.map +1 -1
  247. package/package.json +4 -4
  248. package/src/core/components/Panel.tsx +34 -0
  249. package/src/core/components/SidePanel.tsx +5 -3
  250. package/src/core/components/index.ts +1 -1
  251. package/src/core/components/shadcn/breadcrumb.tsx +49 -30
  252. package/src/core/components/shadcn/button.tsx +3 -2
  253. package/src/core/components/shadcn/filters/filterBar.tsx +3 -3
  254. package/src/core/components/shadcn/index.ts +2 -1
  255. package/src/core/components/shadcn/input.tsx +10 -7
  256. package/src/core/components/shadcn/resizeable.tsx +4 -4
  257. package/src/core/components/shadcn/selectBox.tsx +87 -67
  258. package/src/core/components/shadcn/tabs.tsx +10 -3
  259. package/src/core/components/shadcn/textarea.tsx +21 -0
  260. package/src/core/hooks/index.ts +1 -0
  261. package/src/core/hooks/useScrollableSearch.tsx +193 -0
  262. package/src/env/index.ts +1 -1
  263. package/src/features/agent/chat/ModernAgentConversation.tsx +109 -118
  264. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +2 -22
  265. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +1 -9
  266. package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +39 -55
  267. package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +1 -0
  268. package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +8 -8
  269. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +8 -8
  270. package/src/features/facets/CollectionsFacetsNav.tsx +21 -0
  271. package/src/features/facets/InteractionsFacetsNav.tsx +13 -3
  272. package/src/features/facets/utils/SearchInterface.tsx +5 -1
  273. package/src/features/facets/utils/VTypeFacet.tsx +6 -2
  274. package/src/features/layout/GenericPageNavHeader.tsx +73 -10
  275. package/src/features/store/collections/BrowseCollectionView.tsx +4 -0
  276. package/src/features/store/collections/CreateCollection.tsx +3 -4
  277. package/src/features/store/collections/EditCollectionView.tsx +91 -85
  278. package/src/features/store/collections/SelectCollection.tsx +105 -49
  279. package/src/features/store/objects/DocumentSearchResults.tsx +117 -51
  280. package/src/features/store/objects/DocumentTable.tsx +14 -4
  281. package/src/features/store/objects/components/ContentOverview.tsx +208 -110
  282. package/src/features/store/objects/components/DocumentIcon.tsx +11 -12
  283. package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +12 -2
  284. package/src/features/store/objects/layout/DocumentTableColumn.tsx +16 -1
  285. package/src/features/store/objects/layout/documentLayout.tsx +7 -5
  286. package/src/features/store/objects/layout/knowledge.md +10 -10
  287. package/src/features/store/objects/layout/renderers.tsx +39 -18
  288. package/src/features/store/objects/search/DocumentSearchContext.ts +6 -1
  289. package/src/features/store/objects/search/DocumentSearchProvider.tsx +1 -1
  290. package/src/features/store/objects/selection/ObjectsActionContext.tsx +3 -2
  291. package/src/features/store/objects/selection/SelectionActions.tsx +2 -0
  292. package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +8 -2
  293. package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +22 -2
  294. package/src/features/store/objects/upload/DocumentUploadModal.tsx +18 -9
  295. package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +11 -10
  296. package/src/features/store/types/CreateOrUpdateTypeModal.tsx +1 -1
  297. package/src/router/HistoryNavigator.ts +33 -2
  298. package/src/router/Nav.tsx +4 -3
  299. package/src/widgets/form/Form.tsx +19 -43
  300. package/src/widgets/form/FormContext.ts +5 -2
  301. package/src/widgets/form/fields.tsx +8 -6
  302. package/src/widgets/form/inputs.tsx +1 -0
  303. package/lib/esm/core/components/Textarea.js +0 -15
  304. package/lib/esm/core/components/Textarea.js.map +0 -1
  305. package/lib/types/core/components/Textarea.d.ts +0 -8
  306. package/lib/types/core/components/Textarea.d.ts.map +0 -1
  307. package/src/core/components/Textarea.tsx +0 -25
@@ -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
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;
@@ -154,15 +163,21 @@ function PropertiesPanel({ object, refetch, handleCopyContent }: { object: Conte
154
163
  function DataPanel({ object, loadText, handleCopyContent }: { object: ContentObject, loadText: boolean, handleCopyContent: (content: string, type: "text" | "properties") => Promise<void> }) {
155
164
  const { store } = useUserSession();
156
165
 
157
- const content = object.content;
158
- const isImage =
159
- content && content.type && content.type.startsWith("image/");
166
+ const isImage = object?.metadata?.type === ContentNature.Image;
167
+ const isVideo = object?.metadata?.type === ContentNature.Video;
160
168
 
161
- const [viewImage, setViewImage] = useState(isImage);
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
+ };
162
175
 
176
+ const [currentPanel, setCurrentPanel] = useState<PanelView>(getInitialView());
163
177
 
164
178
  const [text, setText] = useState<string | undefined>(object.text);
165
179
  const [isLoadingText, setIsLoadingText] = useState<boolean>(false);
180
+ const [isTextCropped, setIsTextCropped] = useState<boolean>(false);
166
181
 
167
182
  useEffect(() => {
168
183
  if (loadText && !text) {
@@ -170,7 +185,15 @@ function DataPanel({ object, loadText, handleCopyContent }: { object: ContentObj
170
185
  store.objects
171
186
  .getObjectText(object.id)
172
187
  .then((res) => {
173
- 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
+ }
174
197
  })
175
198
  .catch((err) => {
176
199
  console.error("Failed to load text", err);
@@ -187,36 +210,48 @@ function DataPanel({ object, loadText, handleCopyContent }: { object: ContentObj
187
210
  <div className="flex items-center gap-1 bg-muted mb-2 p-1 rounded">
188
211
  {isImage &&
189
212
  <Button
190
- variant={`${viewImage ? "primary" : "ghost"}`}
213
+ variant={currentPanel === PanelView.Image ? "primary" : "ghost"}
191
214
  size="sm"
192
215
  alt="View Image"
193
- onClick={() => setViewImage(true)}
216
+ onClick={() => setCurrentPanel(PanelView.Image)}
194
217
  >
195
218
  Image
196
219
  </Button>
197
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
+ }
198
231
  <Button
199
- variant={`${viewImage ? "ghost" : "primary"}`}
232
+ variant={currentPanel === PanelView.Text ? "primary" : "ghost"}
200
233
  size="sm"
201
234
  alt="View Text"
202
- onClick={() => setViewImage(false)}
235
+ onClick={() => setCurrentPanel(PanelView.Text)}
203
236
  >
204
237
  Text
205
238
  </Button>
206
239
 
207
240
  </div>
208
- {!viewImage && <TextActions object={object} text={text} handleCopyContent={handleCopyContent} />}
241
+ {currentPanel === PanelView.Text && <TextActions object={object} text={text} handleCopyContent={handleCopyContent} />}
209
242
  </div>
210
243
  {
211
- viewImage ? (
244
+ currentPanel === PanelView.Image ? (
212
245
  <ImagePanel object={object} />
246
+ ) : currentPanel === PanelView.Video ? (
247
+ <VideoPanel object={object} />
213
248
  ) : (
214
249
  isLoadingText ? (
215
250
  <div className="flex justify-center items-center h-[calc(100vh-260px)]">
216
251
  <Spinner size="lg" />
217
252
  </div>
218
253
  ) : (
219
- <TextPanel object={object} text={text} />
254
+ <TextPanel object={object} text={text} isTextCropped={isTextCropped} />
220
255
  )
221
256
  )
222
257
  }
@@ -227,24 +262,29 @@ function DataPanel({ object, loadText, handleCopyContent }: { object: ContentObj
227
262
  function TextActions({ object, text, handleCopyContent }: { object: ContentObject, handleCopyContent: (content: string, type: "text" | "properties") => Promise<void>, text: string | undefined }) {
228
263
  const { client } = useUserSession();
229
264
  const toast = useToast();
265
+ const [loadingFormat, setLoadingFormat] = useState<"docx" | "pdf" | null>(null);
230
266
 
231
267
  const content = object.content;
232
268
 
233
- const isMarkdownOrText =
269
+ const isMarkdown =
234
270
  content &&
235
271
  content.type &&
236
- (content.type === "text/markdown" || content.type === "text/plain");
237
-
238
- // Check for markdown indicators, ignoring any HTML comments
239
- const seemsMarkdown =
240
- text &&
241
- // Look for markdown indicators
242
- (text.includes("\n#") ||
243
- text.includes("\n*") ||
244
- text.includes("\n+") ||
245
- text.includes("!["));
272
+ content.type === "text/markdown";
246
273
 
247
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
+
248
288
  try {
249
289
  // Request document rendition from the server
250
290
  const response = await client.objects.getRendition(object.id, {
@@ -308,6 +348,8 @@ function TextActions({ object, text, handleCopyContent }: { object: ContentObjec
308
348
  description: `Failed to export document to ${format.toUpperCase()} format`,
309
349
  duration: 5000,
310
350
  });
351
+ } finally {
352
+ setLoadingFormat(null);
311
353
  }
312
354
  };
313
355
 
@@ -321,24 +363,34 @@ function TextActions({ object, text, handleCopyContent }: { object: ContentObjec
321
363
  <Copy className="size-4" />
322
364
  </Button>
323
365
  )}
324
- {(isMarkdownOrText || seemsMarkdown) && text && (
366
+ {isMarkdown && text && (
325
367
  <>
326
368
  <Button
327
369
  variant="ghost"
328
370
  size="sm"
329
371
  onClick={handleExportDocx}
372
+ disabled={loadingFormat !== null}
330
373
  className="flex items-center gap-2"
331
374
  >
332
- <Download className="size-4" />
375
+ {loadingFormat === "docx" ? (
376
+ <Spinner size="sm" />
377
+ ) : (
378
+ <Download className="size-4" />
379
+ )}
333
380
  DOCX
334
381
  </Button>
335
382
  <Button
336
383
  variant="ghost"
337
384
  size="sm"
338
385
  onClick={handleExportPdf}
386
+ disabled={loadingFormat !== null}
339
387
  className="flex items-center gap-2"
340
388
  >
341
- <Download className="size-4" />
389
+ {loadingFormat === "pdf" ? (
390
+ <Spinner size="sm" />
391
+ ) : (
392
+ <Download className="size-4" />
393
+ )}
342
394
  PDF
343
395
  </Button>
344
396
  </>
@@ -348,91 +400,43 @@ function TextActions({ object, text, handleCopyContent }: { object: ContentObjec
348
400
  );
349
401
  }
350
402
 
351
- function TextPanel({ object, text }: { object: ContentObject, text: string | undefined }) {
352
- const toast = useToast();
353
- const { client } = useUserSession();
354
-
355
- // Check for markdown indicators, ignoring any HTML comments
356
- const seemsMarkdown =
357
- text &&
358
- // Look for markdown indicators
359
- (text.includes("\n#") ||
360
- text.includes("\n*") ||
361
- text.includes("\n+") ||
362
- text.includes("!["));
363
-
364
- const handleExportDocument = async (format: "docx" | "pdf") => {
365
- try {
366
- // Request document rendition from the server
367
- const response = await client.objects.getRendition(object.id, {
368
- format: format as any, // We're extending the format type
369
- generate_if_missing: true,
370
- sign_url: true,
371
- });
372
-
373
- if (response.status === "generating") {
374
- toast({
375
- status: "info",
376
- title: "Generating document",
377
- description: `Please wait while we prepare your ${format.toUpperCase()} file...`,
378
- duration: 5000,
379
- });
380
-
381
- // Poll for completion
382
- setTimeout(() => handleExportDocument(format), 3000);
383
- return;
384
- }
385
-
386
- if (response.status === "failed") {
387
- throw new Error("Document generation failed");
388
- }
403
+ const TextPanel = memo(({ object, text, isTextCropped }: { object: ContentObject, text: string | undefined, isTextCropped: boolean }) => {
404
+ const content = object.content;
389
405
 
390
- // Download the generated file or open in new window
391
- if (response.renditions && response.renditions.length > 0) {
392
- const downloadUrl = response.renditions[0];
406
+ // Check if content type is markdown or plain text
407
+ const isMarkdownOrText =
408
+ content &&
409
+ content.type &&
410
+ (content.type === "text/markdown" || content.type === "text/plain");
393
411
 
394
- if (format === 'pdf') {
395
- // Open PDF in new window
396
- window.open(downloadUrl, '_blank');
397
- toast({
398
- status: "success",
399
- title: "PDF opened",
400
- description: "PDF document opened in a new window",
401
- duration: 2000,
402
- });
403
- } else {
404
- // Download DOCX file
405
- const link = document.createElement("a");
406
- link.href = downloadUrl;
407
- link.download = `${object.name || "document"}.${format}`;
408
- document.body.appendChild(link);
409
- link.click();
410
- document.body.removeChild(link);
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
+ );
411
423
 
412
- toast({
413
- status: "success",
414
- title: "Document exported",
415
- description: `Successfully exported to ${format.toUpperCase()} format`,
416
- duration: 2000,
417
- });
418
- }
419
- }
420
- } catch (err) {
421
- console.error(`Failed to export document as ${format}:`, err);
422
- toast({
423
- status: "error",
424
- title: "Export failed",
425
- description: `Failed to export document to ${format.toUpperCase()} format`,
426
- duration: 5000,
427
- });
428
- }
429
- };
424
+ // Render as markdown if it's markdown/text type OR if text looks like markdown
425
+ const shouldRenderAsMarkdown = isMarkdownOrText || seemsMarkdown;
430
426
 
431
427
  return (
432
428
  text ? (
433
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>
435
+ </div>
436
+ </div>
437
+ )}
434
438
  <div className="max-w-7xl px-2 h-[calc(100vh-210px)] overflow-auto">
435
- {seemsMarkdown ? (
439
+ {shouldRenderAsMarkdown ? (
436
440
  <div className="vprose prose-sm p-1">
437
441
  <MarkdownRenderer
438
442
  components={{
@@ -511,16 +515,14 @@ function TextPanel({ object, text }: { object: ContentObject, text: string | und
511
515
  <div>No content</div>
512
516
  </div>
513
517
  );
514
- }
518
+ });
515
519
 
516
520
  function ImagePanel({ object }: { object: ContentObject }) {
517
521
  const { client } = useUserSession();
518
522
  const [imageUrl, setImageUrl] = useState<string>();
519
523
 
520
-
521
524
  const content = object.content;
522
- const isImage =
523
- content && content.type && content.type.startsWith("image/");
525
+ const isImage = object.metadata && object.metadata.type === ContentNature.Image;
524
526
 
525
527
  useEffect(() => {
526
528
  if (isImage) {
@@ -569,4 +571,100 @@ function ImagePanel({ object }: { object: ContentObject }) {
569
571
  )}
570
572
  </div>
571
573
  );
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
+ );
572
670
  }
@@ -4,7 +4,6 @@ import { retrieveRendition } from '../../../utils'
4
4
 
5
5
  import { ContentObjectItem } from '@vertesia/common'
6
6
  import { Button, Card, CardContent, Separator, VTooltip } from "@vertesia/ui/core"
7
- import { NavLink } from "@vertesia/ui/router"
8
7
  import { useUserSession } from "@vertesia/ui/session"
9
8
  import { DocumentSelection } from '../DocumentSelectionProvider'
10
9
  import { Eye } from 'lucide-react'
@@ -14,6 +13,8 @@ interface DocumentIconProps {
14
13
  onSelectionChange: ((object: ContentObjectItem, ev: ChangeEvent<HTMLInputElement>) => void);
15
14
  selection: DocumentSelection;
16
15
  onRowClick?: (object: ContentObjectItem) => void;
16
+ previewObject?: (objectId: string) => void;
17
+ selectedObject?: ContentObjectItem | null;
17
18
  }
18
19
 
19
20
  export function DocumentIconSkeleton({ isLoading = false, counts = 6 }: { isLoading?: boolean, counts?: number }) {
@@ -45,7 +46,7 @@ export function DocumentIconSkeleton({ isLoading = false, counts = 6 }: { isLoad
45
46
  )
46
47
  }
47
48
 
48
- export function DocumentIcon({ selection, document, onSelectionChange, onRowClick }: Readonly<DocumentIconProps>) {
49
+ export function DocumentIcon({ selection, document, onSelectionChange, onRowClick, previewObject, selectedObject }: Readonly<DocumentIconProps>) {
49
50
  const { client } = useUserSession()
50
51
 
51
52
  const [renditionUrl, setRenditionUrl] = useState<string | undefined>(undefined)
@@ -67,7 +68,7 @@ export function DocumentIcon({ selection, document, onSelectionChange, onRowClic
67
68
  }, [document])
68
69
 
69
70
  return (
70
- <Card className="relative flex flex-col border h-fit" onClick={() => (onRowClick && onRowClick(document))}>
71
+ <Card className={`relative flex flex-col border h-fit ${selectedObject?.id === document.id ? 'border-attention border-4' : ''}`} onClick={() => (onRowClick && onRowClick(document))}>
71
72
  {
72
73
  selection && (
73
74
  <div
@@ -85,16 +86,14 @@ export function DocumentIcon({ selection, document, onSelectionChange, onRowClic
85
86
  <div
86
87
  className="absolute top-1 right-1 z-10 flex flex-col items-center"
87
88
  >
88
- <NavLink
89
- topLevelNav
90
- href={`/store/objects/${document.id}`}
89
+ <Button
90
+ variant="ghost" size="sm" title="Preivew Object" onClick={(e) => {
91
+ e.stopPropagation();
92
+ previewObject?.(document.id);
93
+ }}
91
94
  >
92
- <Button
93
- variant="ghost" size="sm" title="Open Object"
94
- >
95
- <Eye className={`size-4 ${renditionStatus === 'ready' ? 'text-muted' : 'text-white'}`} />
96
- </Button>
97
- </NavLink>
95
+ <Eye className={`size-4 ${renditionStatus === 'ready' ? 'text-muted' : 'text-white'}`} />
96
+ </Button>
98
97
  </div>
99
98
 
100
99
  {
@@ -1,4 +1,4 @@
1
- import { useState } from 'react';
1
+ import { useState, useEffect } from 'react';
2
2
  import {
3
3
  Button,
4
4
  Modal,
@@ -65,10 +65,20 @@ export function SaveVersionConfirmModal({ isOpen, onClose, onConfirm, isLoading,
65
65
  }
66
66
  ];
67
67
 
68
- const [selectedOption, setSelectedOption] = useState<SaveOptionType | undefined>(saveOptions[0]);
68
+ // Default to "create new version" when replacing a file, "update current version" when editing properties
69
+ const defaultOption = uploadedFileName ? saveOptions[1] : saveOptions[0];
70
+ const [selectedOption, setSelectedOption] = useState<SaveOptionType | undefined>(defaultOption);
69
71
  const [versionLabel, setVersionLabel] = useState('');
70
72
  const optionAdapter = new SaveOptionAdapter();
71
73
 
74
+ // Reset to default when modal opens or uploadedFileName changes
75
+ useEffect(() => {
76
+ if (isOpen) {
77
+ setSelectedOption(defaultOption);
78
+ setVersionLabel('');
79
+ }
80
+ }, [isOpen, uploadedFileName]);
81
+
72
82
  const createVersion = selectedOption?.id === "new-version";
73
83
 
74
84
  const handleOptionChange = (option: SaveOptionType) => {
@@ -37,9 +37,11 @@ export class DocumentTableColumn {
37
37
  renderer: (value: any, index: number) => React.ReactNode = defaultRenderer;
38
38
  path: string[];
39
39
  fallbackPath?: string[];
40
- constructor(public layout: ExtendedColumnLayout) {
40
+ previewObject?: (objectId: string) => void;
41
+ constructor(public layout: ExtendedColumnLayout, previewObject?: (objectId: string) => void) {
41
42
  this.path = splitPath(layout.field || '');
42
43
  this.fallbackPath = layout.fallback ? splitPath(layout.fallback) : undefined;
44
+ this.previewObject = previewObject;
43
45
 
44
46
  // If there's a custom render function, use it
45
47
  if (layout.render) {
@@ -78,6 +80,19 @@ export class DocumentTableColumn {
78
80
  if (this.layout.render) {
79
81
  return <td key={index} className="whitespace-nowrap px-3 py-4 text-sm">{this.layout.render(object)}</td>;
80
82
  }
83
+
84
+ const type = this.layout.type || 'string';
85
+ const baseType = type.indexOf('?') > 0 ? type.substring(0, type.indexOf('?')) : type;
86
+
87
+ if (baseType === 'objectId' && this.previewObject) {
88
+ const i = type.indexOf('?');
89
+ const params = i > 0 ? new URLSearchParams(type.substring(i + 1)) : undefined;
90
+ const objectIdRenderer = renderers.objectId(params, (_id: string) => {
91
+ this.previewObject!(object.id);
92
+ });
93
+ return objectIdRenderer(object, index);
94
+ }
95
+
81
96
  // Otherwise use the type-based renderer with the resolved value
82
97
  return this.renderer(this.resolveValue(object), index);
83
98
  }
@@ -10,13 +10,15 @@ interface ViewProps {
10
10
  isLoading: boolean;
11
11
  layout?: ColumnLayout[];
12
12
  onRowClick?: (object: ContentObjectItem) => void;
13
+ previewObject?: (objectId: string) => void;
14
+ selectedObject?: ContentObjectItem | null;
13
15
  onSelectionChange: ((object: ContentObjectItem, ev: ChangeEvent<HTMLInputElement>) => void);
14
16
  selection: DocumentSelection;
15
17
  toggleAll?: (ev: ChangeEvent<HTMLInputElement>) => void;
16
18
  columns: DocumentTableColumn[];
17
19
  }
18
20
 
19
- export function DocumentTableView({ objects, selection, isLoading, onRowClick, columns, toggleAll, onSelectionChange }: ViewProps) {
21
+ export function DocumentTableView({ objects, selection, isLoading, columns, onRowClick, selectedObject, toggleAll, onSelectionChange }: ViewProps) {
20
22
  return (
21
23
  <Table className="w-full border-t">
22
24
  <thead>
@@ -31,12 +33,12 @@ export function DocumentTableView({ objects, selection, isLoading, onRowClick, c
31
33
  {
32
34
  objects?.map((obj: ContentObjectItem) => {
33
35
  return (
34
- <tr key={obj.id} className='cursor-pointer hover:bg-muted' onClick={() => {
36
+ <tr key={obj.id} className={`cursor-pointer hover:bg-muted group ${selectedObject?.id === obj.id ? 'bg-muted' : ''}`} onClick={() => {
35
37
  onRowClick && onRowClick(obj)
36
38
  }}>
37
39
  {selection &&
38
40
  <td onClick={ev => ev.stopPropagation()}>
39
- <input checked={selection.isSelected(obj.id)} type="checkbox"
41
+ <input checked={selection.isSelected(obj.id)} type="checkbox" className={`${!selection.isSelected(obj.id) ? 'hidden group-hover:block' : ''}`}
40
42
  onChange={(ev: ChangeEvent<HTMLInputElement>) => onSelectionChange(obj, ev)} />
41
43
  </td>
42
44
  }
@@ -51,13 +53,13 @@ export function DocumentTableView({ objects, selection, isLoading, onRowClick, c
51
53
  )
52
54
  }
53
55
 
54
- export function DocumentGridView({ objects, selection, isLoading, onSelectionChange, onRowClick }: ViewProps) {
56
+ export function DocumentGridView({ objects, selection, isLoading, onSelectionChange, onRowClick, previewObject, selectedObject }: ViewProps) {
55
57
  return (
56
58
  <>
57
59
  <DocumentIconSkeleton isLoading={isLoading} />
58
60
  <div className="w-full gap-2 grid lg:grid-cols-6">
59
61
  {objects.map((document) => (
60
- <DocumentIcon key={document.id} document={document} selection={selection} onSelectionChange={onSelectionChange} onRowClick={onRowClick} />
62
+ <DocumentIcon key={document.id} document={document} selection={selection} onSelectionChange={onSelectionChange} onRowClick={onRowClick} previewObject={previewObject} selectedObject={selectedObject} />
61
63
  ))}
62
64
  </div>
63
65
  </>