@vertesia/ui 0.79.0 → 0.80.0-dev-20251118

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 (296) 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/index.js +1 -1
  8. package/lib/esm/core/components/index.js.map +1 -1
  9. package/lib/esm/core/components/shadcn/breadcrumb.js +29 -8
  10. package/lib/esm/core/components/shadcn/breadcrumb.js.map +1 -1
  11. package/lib/esm/core/components/shadcn/button.js +3 -2
  12. package/lib/esm/core/components/shadcn/button.js.map +1 -1
  13. package/lib/esm/core/components/shadcn/filters/filterBar.js +2 -2
  14. package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
  15. package/lib/esm/core/components/shadcn/index.js +1 -0
  16. package/lib/esm/core/components/shadcn/index.js.map +1 -1
  17. package/lib/esm/core/components/shadcn/input.js +4 -1
  18. package/lib/esm/core/components/shadcn/input.js.map +1 -1
  19. package/lib/esm/core/components/shadcn/resizeable.js +2 -2
  20. package/lib/esm/core/components/shadcn/resizeable.js.map +1 -1
  21. package/lib/esm/core/components/shadcn/selectBox.js +15 -9
  22. package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
  23. package/lib/esm/core/components/shadcn/tabs.js +10 -3
  24. package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
  25. package/lib/esm/core/components/shadcn/textarea.js +7 -0
  26. package/lib/esm/core/components/shadcn/textarea.js.map +1 -0
  27. package/lib/esm/core/hooks/CompositeState.js +139 -1
  28. package/lib/esm/core/hooks/CompositeState.js.map +1 -1
  29. package/lib/esm/core/hooks/index.js +1 -0
  30. package/lib/esm/core/hooks/index.js.map +1 -1
  31. package/lib/esm/core/hooks/useScrollableSearch.js +92 -0
  32. package/lib/esm/core/hooks/useScrollableSearch.js.map +1 -0
  33. package/lib/esm/env/index.js +1 -1
  34. package/lib/esm/env/index.js.map +1 -1
  35. package/lib/esm/features/agent/PayloadBuilder.js +80 -55
  36. package/lib/esm/features/agent/PayloadBuilder.js.map +1 -1
  37. package/lib/esm/features/agent/chat/ModernAgentConversation.js +22 -24
  38. package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
  39. package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +2 -3
  40. package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  41. package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +2 -2
  42. package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  43. package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +15 -20
  44. package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
  45. package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js +1 -0
  46. package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js.map +1 -1
  47. package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js +3 -3
  48. package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js.map +1 -1
  49. package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +6 -6
  50. package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  51. package/lib/esm/features/facets/CollectionsFacetsNav.js +19 -0
  52. package/lib/esm/features/facets/CollectionsFacetsNav.js.map +1 -1
  53. package/lib/esm/features/facets/InteractionsFacetsNav.js +9 -3
  54. package/lib/esm/features/facets/InteractionsFacetsNav.js.map +1 -1
  55. package/lib/esm/features/facets/utils/VTypeFacet.js +4 -1
  56. package/lib/esm/features/facets/utils/VTypeFacet.js.map +1 -1
  57. package/lib/esm/features/layout/GenericPageNavHeader.js +58 -5
  58. package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -1
  59. package/lib/esm/features/store/collections/BrowseCollectionView.js +3 -0
  60. package/lib/esm/features/store/collections/BrowseCollectionView.js.map +1 -1
  61. package/lib/esm/features/store/collections/CreateCollection.js +2 -2
  62. package/lib/esm/features/store/collections/CreateCollection.js.map +1 -1
  63. package/lib/esm/features/store/collections/EditCollectionView.js +29 -30
  64. package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
  65. package/lib/esm/features/store/collections/SelectCollection.js +46 -45
  66. package/lib/esm/features/store/collections/SelectCollection.js.map +1 -1
  67. package/lib/esm/features/store/objects/DocumentSearchResults.js +35 -9
  68. package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
  69. package/lib/esm/features/store/objects/DocumentTable.js +6 -6
  70. package/lib/esm/features/store/objects/DocumentTable.js.map +1 -1
  71. package/lib/esm/features/store/objects/components/ContentOverview.js +158 -114
  72. package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
  73. package/lib/esm/features/store/objects/components/DocumentIcon.js +5 -3
  74. package/lib/esm/features/store/objects/components/DocumentIcon.js.map +1 -1
  75. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js +11 -2
  76. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -1
  77. package/lib/esm/features/store/objects/components/useDownloadObject.js +2 -2
  78. package/lib/esm/features/store/objects/components/useDownloadObject.js.map +1 -1
  79. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +13 -1
  80. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  81. package/lib/esm/features/store/objects/layout/documentLayout.js +5 -5
  82. package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -1
  83. package/lib/esm/features/store/objects/layout/renderers.js +28 -12
  84. package/lib/esm/features/store/objects/layout/renderers.js.map +1 -1
  85. package/lib/esm/features/store/objects/search/DocumentSearchContext.js +5 -1
  86. package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  87. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js +1 -1
  88. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js.map +1 -1
  89. package/lib/esm/features/store/objects/selection/ObjectsActionContext.js +3 -2
  90. package/lib/esm/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
  91. package/lib/esm/features/store/objects/selection/SelectionActions.js +2 -0
  92. package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
  93. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js +10 -2
  94. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js.map +1 -1
  95. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js +20 -2
  96. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
  97. package/lib/esm/features/store/objects/upload/DocumentUploadModal.js +15 -7
  98. package/lib/esm/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
  99. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js +1 -1
  100. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js.map +1 -1
  101. package/lib/esm/features/user/UserInfo.js +2 -0
  102. package/lib/esm/features/user/UserInfo.js.map +1 -1
  103. package/lib/esm/router/HistoryNavigator.js +25 -2
  104. package/lib/esm/router/HistoryNavigator.js.map +1 -1
  105. package/lib/esm/router/Nav.js +3 -3
  106. package/lib/esm/router/Nav.js.map +1 -1
  107. package/lib/esm/session/UserSession.js +1 -0
  108. package/lib/esm/session/UserSession.js.map +1 -1
  109. package/lib/esm/session/UserSessionProvider.js +9 -2
  110. package/lib/esm/session/UserSessionProvider.js.map +1 -1
  111. package/lib/esm/session/auth/composable.js +66 -67
  112. package/lib/esm/session/auth/composable.js.map +1 -1
  113. package/lib/esm/widgets/form/Form.js +17 -30
  114. package/lib/esm/widgets/form/Form.js.map +1 -1
  115. package/lib/esm/widgets/form/FormContext.js +4 -2
  116. package/lib/esm/widgets/form/FormContext.js.map +1 -1
  117. package/lib/esm/widgets/form/ManagedObject.js +4 -0
  118. package/lib/esm/widgets/form/ManagedObject.js.map +1 -1
  119. package/lib/esm/widgets/form/fields.js +4 -3
  120. package/lib/esm/widgets/form/fields.js.map +1 -1
  121. package/lib/esm/widgets/form/inputs.js +2 -0
  122. package/lib/esm/widgets/form/inputs.js.map +1 -1
  123. package/lib/tsconfig.tsbuildinfo +1 -1
  124. package/lib/types/core/components/Panel.d.ts +11 -0
  125. package/lib/types/core/components/Panel.d.ts.map +1 -0
  126. package/lib/types/core/components/SidePanel.d.ts.map +1 -1
  127. package/lib/types/core/components/index.d.ts +1 -1
  128. package/lib/types/core/components/index.d.ts.map +1 -1
  129. package/lib/types/core/components/shadcn/breadcrumb.d.ts +3 -2
  130. package/lib/types/core/components/shadcn/breadcrumb.d.ts.map +1 -1
  131. package/lib/types/core/components/shadcn/button.d.ts.map +1 -1
  132. package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  133. package/lib/types/core/components/shadcn/index.d.ts +1 -0
  134. package/lib/types/core/components/shadcn/index.d.ts.map +1 -1
  135. package/lib/types/core/components/shadcn/input.d.ts.map +1 -1
  136. package/lib/types/core/components/shadcn/selectBox.d.ts +3 -2
  137. package/lib/types/core/components/shadcn/selectBox.d.ts.map +1 -1
  138. package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
  139. package/lib/types/core/components/shadcn/textarea.d.ts +4 -0
  140. package/lib/types/core/components/shadcn/textarea.d.ts.map +1 -0
  141. package/lib/types/core/hooks/CompositeState.d.ts +115 -6
  142. package/lib/types/core/hooks/CompositeState.d.ts.map +1 -1
  143. package/lib/types/core/hooks/index.d.ts +1 -0
  144. package/lib/types/core/hooks/index.d.ts.map +1 -1
  145. package/lib/types/core/hooks/useScrollableSearch.d.ts +82 -0
  146. package/lib/types/core/hooks/useScrollableSearch.d.ts.map +1 -0
  147. package/lib/types/env/index.d.ts +3 -1
  148. package/lib/types/env/index.d.ts.map +1 -1
  149. package/lib/types/features/agent/PayloadBuilder.d.ts +11 -19
  150. package/lib/types/features/agent/PayloadBuilder.d.ts.map +1 -1
  151. package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  152. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +1 -1
  153. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  154. package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
  155. package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
  156. package/lib/types/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts.map +1 -1
  157. package/lib/types/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  158. package/lib/types/features/facets/InteractionsFacetsNav.d.ts +1 -0
  159. package/lib/types/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
  160. package/lib/types/features/facets/utils/SearchInterface.d.ts +6 -1
  161. package/lib/types/features/facets/utils/SearchInterface.d.ts.map +1 -1
  162. package/lib/types/features/facets/utils/VTypeFacet.d.ts +2 -1
  163. package/lib/types/features/facets/utils/VTypeFacet.d.ts.map +1 -1
  164. package/lib/types/features/layout/GenericPageNavHeader.d.ts +2 -1
  165. package/lib/types/features/layout/GenericPageNavHeader.d.ts.map +1 -1
  166. package/lib/types/features/store/collections/BrowseCollectionView.d.ts.map +1 -1
  167. package/lib/types/features/store/collections/CreateCollection.d.ts.map +1 -1
  168. package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
  169. package/lib/types/features/store/collections/SelectCollection.d.ts +6 -4
  170. package/lib/types/features/store/collections/SelectCollection.d.ts.map +1 -1
  171. package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  172. package/lib/types/features/store/objects/DocumentTable.d.ts +4 -0
  173. package/lib/types/features/store/objects/DocumentTable.d.ts.map +1 -1
  174. package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  175. package/lib/types/features/store/objects/components/DocumentIcon.d.ts +3 -1
  176. package/lib/types/features/store/objects/components/DocumentIcon.d.ts.map +1 -1
  177. package/lib/types/features/store/objects/components/SaveVersionConfirmModal.d.ts.map +1 -1
  178. package/lib/types/features/store/objects/components/useDownloadObject.d.ts +1 -1
  179. package/lib/types/features/store/objects/components/useDownloadObject.d.ts.map +1 -1
  180. package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts +2 -1
  181. package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  182. package/lib/types/features/store/objects/layout/documentLayout.d.ts +4 -2
  183. package/lib/types/features/store/objects/layout/documentLayout.d.ts.map +1 -1
  184. package/lib/types/features/store/objects/layout/renderers.d.ts +1 -1
  185. package/lib/types/features/store/objects/layout/renderers.d.ts.map +1 -1
  186. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +1 -0
  187. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  188. package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
  189. package/lib/types/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
  190. package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts +1 -0
  191. package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
  192. package/lib/types/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
  193. package/lib/types/features/user/UserInfo.d.ts.map +1 -1
  194. package/lib/types/router/HistoryNavigator.d.ts.map +1 -1
  195. package/lib/types/router/Nav.d.ts +2 -1
  196. package/lib/types/router/Nav.d.ts.map +1 -1
  197. package/lib/types/session/UserSession.d.ts.map +1 -1
  198. package/lib/types/session/UserSessionProvider.d.ts.map +1 -1
  199. package/lib/types/session/auth/composable.d.ts.map +1 -1
  200. package/lib/types/widgets/form/Form.d.ts +2 -1
  201. package/lib/types/widgets/form/Form.d.ts.map +1 -1
  202. package/lib/types/widgets/form/FormContext.d.ts +5 -2
  203. package/lib/types/widgets/form/FormContext.d.ts.map +1 -1
  204. package/lib/types/widgets/form/ManagedObject.d.ts.map +1 -1
  205. package/lib/types/widgets/form/fields.d.ts +2 -2
  206. package/lib/types/widgets/form/fields.d.ts.map +1 -1
  207. package/lib/types/widgets/form/inputs.d.ts.map +1 -1
  208. package/lib/vertesia-ui-core.js +1 -1
  209. package/lib/vertesia-ui-core.js.map +1 -1
  210. package/lib/vertesia-ui-env.js +1 -1
  211. package/lib/vertesia-ui-env.js.map +1 -1
  212. package/lib/vertesia-ui-features.js +1 -1
  213. package/lib/vertesia-ui-features.js.map +1 -1
  214. package/lib/vertesia-ui-router.js +1 -1
  215. package/lib/vertesia-ui-router.js.map +1 -1
  216. package/lib/vertesia-ui-session.js +1 -1
  217. package/lib/vertesia-ui-session.js.map +1 -1
  218. package/lib/vertesia-ui-shell.js.map +1 -1
  219. package/lib/vertesia-ui-widgets.js +1 -1
  220. package/lib/vertesia-ui-widgets.js.map +1 -1
  221. package/package.json +170 -165
  222. package/src/core/components/Panel.tsx +34 -0
  223. package/src/core/components/SelectBox.tsx +1 -1
  224. package/src/core/components/SidePanel.tsx +5 -3
  225. package/src/core/components/TagsInput.tsx +388 -0
  226. package/src/core/components/index.ts +2 -1
  227. package/src/core/components/shadcn/breadcrumb.tsx +49 -30
  228. package/src/core/components/shadcn/button.tsx +3 -2
  229. package/src/core/components/shadcn/filters/filterBar.tsx +3 -3
  230. package/src/core/components/shadcn/index.ts +2 -1
  231. package/src/core/components/shadcn/input.tsx +10 -7
  232. package/src/core/components/shadcn/popover.tsx +2 -2
  233. package/src/core/components/shadcn/resizeable.tsx +4 -4
  234. package/src/core/components/shadcn/selectBox.tsx +87 -67
  235. package/src/core/components/shadcn/tabs.tsx +10 -3
  236. package/src/core/components/shadcn/textarea.tsx +21 -0
  237. package/src/core/hooks/CompositeState.tsx +156 -6
  238. package/src/core/hooks/index.ts +1 -0
  239. package/src/core/hooks/useScrollableSearch.tsx +193 -0
  240. package/src/env/index.ts +4 -3
  241. package/src/features/agent/PayloadBuilder.tsx +92 -65
  242. package/src/features/agent/chat/ModernAgentConversation.tsx +109 -118
  243. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +3 -23
  244. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +3 -11
  245. package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +39 -55
  246. package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +1 -0
  247. package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +8 -8
  248. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +9 -9
  249. package/src/features/facets/CollectionsFacetsNav.tsx +21 -0
  250. package/src/features/facets/InteractionsFacetsNav.tsx +13 -3
  251. package/src/features/facets/utils/SearchInterface.tsx +5 -1
  252. package/src/features/facets/utils/VTypeFacet.tsx +6 -2
  253. package/src/features/layout/GenericPageNavHeader.tsx +73 -10
  254. package/src/features/store/collections/BrowseCollectionView.tsx +4 -0
  255. package/src/features/store/collections/CreateCollection.tsx +3 -4
  256. package/src/features/store/collections/EditCollectionView.tsx +112 -85
  257. package/src/features/store/collections/SelectCollection.tsx +105 -49
  258. package/src/features/store/collections/SharedPropsEditor.tsx +61 -0
  259. package/src/features/store/collections/SyncMemberHeadsToggle.tsx +48 -0
  260. package/src/features/store/collections/index.ts +3 -1
  261. package/src/features/store/objects/DocumentSearchResults.tsx +128 -53
  262. package/src/features/store/objects/DocumentTable.tsx +14 -4
  263. package/src/features/store/objects/components/ContentOverview.tsx +208 -110
  264. package/src/features/store/objects/components/DocumentIcon.tsx +11 -12
  265. package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +12 -2
  266. package/src/features/store/objects/components/useDownloadObject.ts +7 -2
  267. package/src/features/store/objects/layout/DocumentTableColumn.tsx +16 -1
  268. package/src/features/store/objects/layout/documentLayout.tsx +7 -5
  269. package/src/features/store/objects/layout/knowledge.md +10 -10
  270. package/src/features/store/objects/layout/renderers.tsx +39 -18
  271. package/src/features/store/objects/search/DocumentSearchContext.ts +6 -1
  272. package/src/features/store/objects/search/DocumentSearchProvider.tsx +1 -1
  273. package/src/features/store/objects/selection/ObjectsActionContext.tsx +3 -2
  274. package/src/features/store/objects/selection/SelectionActions.tsx +2 -0
  275. package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +8 -2
  276. package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +22 -2
  277. package/src/features/store/objects/upload/DocumentUploadModal.tsx +18 -9
  278. package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +10 -7
  279. package/src/features/store/types/CreateOrUpdateTypeModal.tsx +1 -1
  280. package/src/features/user/UserInfo.tsx +2 -0
  281. package/src/router/HistoryNavigator.ts +33 -2
  282. package/src/router/Nav.tsx +4 -3
  283. package/src/session/UserSession.ts +1 -0
  284. package/src/session/UserSessionProvider.tsx +10 -2
  285. package/src/session/auth/composable.ts +71 -70
  286. package/src/shell/apps/AppProjectSelector.tsx +2 -2
  287. package/src/widgets/form/Form.tsx +19 -43
  288. package/src/widgets/form/FormContext.ts +5 -2
  289. package/src/widgets/form/ManagedObject.ts +4 -0
  290. package/src/widgets/form/fields.tsx +8 -6
  291. package/src/widgets/form/inputs.tsx +1 -0
  292. package/lib/esm/core/components/Textarea.js +0 -15
  293. package/lib/esm/core/components/Textarea.js.map +0 -1
  294. package/lib/types/core/components/Textarea.d.ts +0 -8
  295. package/lib/types/core/components/Textarea.d.ts.map +0 -1
  296. package/src/core/components/Textarea.tsx +0 -25
@@ -1,9 +1,13 @@
1
1
  import { json } from "@codemirror/lang-json";
2
- import { Collection, CreateCollectionPayload } from "@vertesia/common";
3
- import { Button, ErrorBox, FormItem, Input, Styles, useFetch, useToast } from "@vertesia/ui/core";
2
+ import { Collection, CreateCollectionPayload, JSONSchemaObject } from "@vertesia/common";
3
+ import { Button, ErrorBox, FormItem, Input, Panel, Styles, Textarea, useFetch, useToast } from "@vertesia/ui/core";
4
+ import { UserInfo } from "@vertesia/ui/features";
5
+ import { SharedPropsEditor } from "@vertesia/ui/features";
6
+ import { SyncMemberHeadsToggle } from "@vertesia/ui/features";
4
7
  import { useUserSession } from "@vertesia/ui/session";
5
- import { CodeMirrorEditor, EditorApi, GeneratedForm, ManagedObject } from "@vertesia/ui/widgets";
8
+ import { CodeMirrorEditor, EditorApi, GeneratedForm, ManagedObject, Node } from "@vertesia/ui/widgets";
6
9
  import { basicSetup } from "codemirror";
10
+ import dayjs from "dayjs";
7
11
  import { useMemo, useRef, useState } from "react";
8
12
  import { SelectContentType, stringifyTableLayout } from "../types";
9
13
 
@@ -54,7 +58,7 @@ export function EditCollectionView({ refetch, collection }: EditCollectionViewPr
54
58
  });
55
59
  return;
56
60
  }
57
-
61
+
58
62
  const payload: Partial<CreateCollectionPayload> = {
59
63
  name: metadata.name,
60
64
  description: metadata.description,
@@ -131,64 +135,94 @@ export function EditCollectionView({ refetch, collection }: EditCollectionViewPr
131
135
 
132
136
  return (
133
137
  <div className="flex flex-col gap-4 py-2">
134
- <FormItem label="Name" required>
135
- <Input value={metadata.name} onChange={(v) => setField("name", v)} />
136
- </FormItem>
137
- <FormItem label="Description">
138
- <textarea
139
- className={Styles.INPUT}
140
- value={metadata.description}
141
- onChange={(e) => setField("description", e.target.value)}
142
- />
143
- </FormItem>
144
- {
145
- !collection.dynamic &&
146
- <FormItem label="Allowed Content Types" description="Select which content types can be added to the collection. If not set, then all content types are allowed.">
138
+ <Panel title="Configuration"
139
+ action={
140
+ <Button size="lg" isDisabled={isUpdating} onClick={onSubmit}>
141
+ Save
142
+ </Button>
143
+ }>
144
+ <div className="flex justify-between mb-2">
145
+ <div className="w-1/2 gap-2 flex flex-col">
146
+ <div className="text-sm font-medium mb-1">Created By</div>
147
+ <div className="gap-2 flex items-center">
148
+ <UserInfo userRef={collection.created_by} showTitle />
149
+ <span>at {dayjs(collection.created_at).format("YYYY-MM-DD HH:mm:ss")}</span>
150
+ </div>
151
+ </div>
152
+ <div className="w-1/2 gap-2 flex flex-col">
153
+ <div className="text-sm font-medium mb-1">Updated By</div>
154
+ <div className="gap-2 flex items-center">
155
+ <UserInfo userRef={collection.updated_by} showTitle />
156
+ <span>at {dayjs(collection.updated_at).format("YYYY-MM-DD HH:mm:ss")}</span>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ <FormItem label="Name" required>
161
+ <Input value={metadata.name} onChange={(v) => setField("name", v)} />
162
+ </FormItem>
163
+ <FormItem label="Description">
164
+ <Textarea
165
+ value={metadata.description}
166
+ onChange={(e) => setField("description", e)}
167
+ />
168
+ </FormItem>
169
+ {
170
+ !collection.dynamic &&
171
+ <FormItem label="Allowed Content Types" description="Select which content types can be added to the collection. If not set, then all content types are allowed.">
172
+ <SelectContentType
173
+ defaultValue={metadata.allowed_types || null}
174
+ onChange={(v) => {
175
+ if (Array.isArray(v)) {
176
+ setField("allowed_types", v.map(type => type.id));
177
+ } else {
178
+ setField("allowed_types", v ? [v.id] : []);
179
+ }
180
+ }}
181
+ isClearable multiple
182
+ />
183
+ </FormItem>
184
+ }
185
+ {
186
+ collection.dynamic && (
187
+ <FormItem label="Query" description="Define the query to dynamically fetch content for the collection.">
188
+ <Textarea
189
+ className={Styles.INPUT}
190
+ value={metadata.query}
191
+ onChange={(e) => setField("query", e)}
192
+ />
193
+ </FormItem>
194
+ )
195
+ }
196
+ <FormItem label="Table Layout" description="Define a custom layout for displaying the collection in tables.">
197
+ <CodeMirrorEditor className="border-1 rounded-md border-border"
198
+ value={tableLayoutValue} extensions={extensions} editorRef={tableLayoutRef} />
199
+ </FormItem>
200
+ <FormItem label="Type" description="Select a content type to assign custom properties and data to the collection.">
147
201
  <SelectContentType
148
- defaultValue={metadata.allowed_types || null}
202
+ defaultValue={metadata.type || null}
149
203
  onChange={(v) => {
150
204
  if (Array.isArray(v)) {
151
- setField("allowed_types", v.map(type => type.id));
205
+ setField("type", v.length > 0 ? v[0].id : null);
152
206
  } else {
153
- setField("allowed_types", v ? [v.id] : []);
207
+ setField("type", v?.id || null);
154
208
  }
155
209
  }}
156
- isClearable multiple
157
- />
158
- </FormItem>
159
- }
160
- {collection.dynamic && (
161
- <FormItem label="Query" description="Define the query to dynamically fetch content for the collection.">
162
- <textarea
163
- className={Styles.INPUT}
164
- value={metadata.query}
165
- onChange={(e) => setField("query", e.target.value)}
210
+ isClearable
166
211
  />
167
212
  </FormItem>
168
- )}
169
- <FormItem label="Table Layout" description="Define a custom layout for displaying the collection in tables.">
170
- <CodeMirrorEditor className="border-1 rounded-md border-border"
171
- value={tableLayoutValue} extensions={extensions} editorRef={tableLayoutRef} />
172
- </FormItem>
173
- <FormItem label="Type" description="Select a content type to assign custom properties and data to the collection.">
174
- <SelectContentType
175
- defaultValue={metadata.type || null}
176
- onChange={(v) => {
177
- if (Array.isArray(v)) {
178
- setField("type", v.length > 0 ? v[0].id : null);
179
- } else {
180
- setField("type", v?.id || null);
181
- }
182
- }}
183
- isClearable
184
- />
185
- </FormItem>
186
- <Button size="lg" className="w-min my-4" isDisabled={isUpdating} onClick={onSubmit}>
187
- Save Metadata
188
- </Button>
213
+ </Panel>
189
214
 
190
215
  {typeId && <PropertiesEditor typeId={typeId} collection={collection} />}
191
- </div>
216
+ {
217
+ !collection.dynamic && (
218
+ <>
219
+ <SyncMemberHeadsToggle collection={collection} />
220
+ <SharedPropsEditor collection={collection} />
221
+ </>
222
+ )
223
+ }
224
+
225
+ </div >
192
226
  );
193
227
  }
194
228
 
@@ -197,30 +231,28 @@ interface PropertiesEditorProps {
197
231
  collection: Collection;
198
232
  }
199
233
  function PropertiesEditor({ typeId, collection }: PropertiesEditorProps) {
234
+ const [formData, setFormData] = useState<JSONSchemaObject>({});
235
+ const toast = useToast();
200
236
  const { client } = useUserSession();
237
+ const [isUpdating, setIsUpdating] = useState(false);
238
+
201
239
  const { data: type, error } = useFetch(() => client.store.types.retrieve(typeId), [typeId]);
240
+ const schema = type?.object_schema || {};
241
+ const object = useMemo(() => new ManagedObject(schema, collection.properties || {}), [schema, collection.properties]);
242
+
202
243
  if (error) {
203
244
  return <ErrorBox title="Failed to load type">{error.message}</ErrorBox>;
204
245
  }
205
246
 
206
- return (
207
- <Section title="Properties">
208
- {type && <PropertiesForm collection={collection} schema={type.object_schema} />}
209
- </Section>
210
- );
211
- }
247
+ if (!type) {
248
+ return null;
249
+ }
212
250
 
213
- interface PropertiesFormProps {
214
- schema: any;
215
- collection: Collection;
216
- }
217
- function PropertiesForm({ schema = {}, collection }: PropertiesFormProps) {
218
- const { client } = useUserSession();
219
- const toast = useToast();
220
- const object = useMemo(() => new ManagedObject(schema, collection.properties || {}), [schema, collection]);
221
- const [isUpdating, setIsUpdating] = useState(false);
222
251
 
223
- const _onSave = (data: any) => {
252
+ const _onSave = (data: JSONSchemaObject) => {
253
+ if (!data || !Object.keys(data).length) {
254
+ return;
255
+ }
224
256
  const payload = { properties: data || {} };
225
257
  setIsUpdating(true);
226
258
  client.store.collections
@@ -246,24 +278,19 @@ function PropertiesForm({ schema = {}, collection }: PropertiesFormProps) {
246
278
  });
247
279
  };
248
280
 
249
- return (
250
- <GeneratedForm object={object} onSubmit={_onSave}>
251
- <Button size="lg" isLoading={isUpdating} className="my-4" variant="primary" type="submit">
252
- Save Properties
253
- </Button>
254
- </GeneratedForm>
255
- );
256
- }
281
+ const onDataChanged = (data: Node) => {
282
+ if (data instanceof ManagedObject) {
283
+ setFormData(data.value);
284
+ }
285
+ }
257
286
 
258
- interface SectionProps {
259
- children: React.ReactNode;
260
- title: string;
261
- }
262
- function Section({ children, title }: SectionProps) {
263
287
  return (
264
- <div className="my-4">
265
- <div className="text-lg text-gray-700 font-semibold border-b border-b-gray-300 py-2 mb-4">{title}</div>
266
- {children}
267
- </div>
288
+ <Panel title="Properties" action={
289
+ <Button size="lg" isLoading={isUpdating} type="submit" onClick={() => _onSave(formData)}>
290
+ Save
291
+ </Button>}
292
+ >
293
+ <GeneratedForm object={object} onChange={onDataChanged} />
294
+ </Panel>
268
295
  );
269
296
  }
@@ -16,19 +16,24 @@ import { useUserSession } from "@vertesia/ui/session";
16
16
  * @returns A dropdown to select a collection.
17
17
  **/
18
18
  interface SelectCollectionProps {
19
- value?: string; // Collection ID
20
- onChange: (collectionId: string | undefined, collection?: CollectionItem) => void;
19
+ value?: string | string[];
20
+ onChange: (collectionId: string | string[] | undefined, collection?: CollectionItem | CollectionItem[]) => void;
21
21
  disabled?: boolean;
22
22
  placeholder?: string;
23
23
  searchPlaceholder?: string;
24
+ filterOut?: string[]; // collection IDs to filter out from the list
25
+ allowDynamic?: boolean;
26
+ multiple?: boolean;
24
27
  }
25
- export function SelectCollection({ onChange, value, disabled = false, placeholder = "Select a collection", searchPlaceholder = "Search collections" }: SelectCollectionProps) {
28
+
29
+ export function SelectCollection({ onChange, value, disabled = false, placeholder = "Select a collection", searchPlaceholder = "Search collections", filterOut, allowDynamic = true, multiple = false }: SelectCollectionProps) {
26
30
  const { client } = useUserSession();
27
31
 
28
32
  const [searchQuery, setSearchQuery] = useState('');
29
33
  const [isSearching, setIsSearching] = useState(false);
34
+ const [useServerSearch, setUseServerSearch] = useState(false);
30
35
 
31
- // Debounce the search query to avoid excessive API calls
36
+ // Debounce the search query to avoid excessive API calls (only used for server-side search)
32
37
  const debouncedSearchQuery = useDebounce(searchQuery, 300);
33
38
 
34
39
  // Memoize the search function to prevent unnecessary re-renders
@@ -37,29 +42,63 @@ export function SelectCollection({ onChange, value, disabled = false, placeholde
37
42
  const trimmedQuery = query.trim();
38
43
 
39
44
  const collections = await client.store.collections.search({
40
- dynamic: false,
41
- name: trimmedQuery || undefined
45
+ dynamic: allowDynamic ? undefined : false,
46
+ name: useServerSearch ? (trimmedQuery || undefined) : undefined
42
47
  });
43
48
 
44
49
  setIsSearching(false);
50
+
51
+ // Check if we hit the maximum limit (1000 collections) - if so, enable server-side search
52
+ if (!useServerSearch && collections.length >= 1000) {
53
+ setUseServerSearch(true);
54
+ }
55
+
56
+ // Filter out collections if filterOut is provided
57
+ if (filterOut && filterOut.length > 0) {
58
+ return collections.filter(col => !filterOut.includes(col.id));
59
+ }
45
60
  return collections;
46
- }, [client]);
61
+ }, [client, allowDynamic, filterOut, useServerSearch]);
47
62
 
48
- // Fetch collections based on debounced search query
63
+ // Fetch collections based on search mode
49
64
  const { data: collections, error } = useFetch(
50
- () => searchCollections(debouncedSearchQuery),
51
- [debouncedSearchQuery, searchCollections]
65
+ () => searchCollections(useServerSearch ? debouncedSearchQuery : ''),
66
+ [useServerSearch ? debouncedSearchQuery : '', searchCollections]
52
67
  );
53
68
 
54
- // Memoize the selected collection to avoid recalculation on every render
69
+ // Memoize the selected collection(s)
55
70
  const selectedCollection = useMemo(() => {
56
- return collections?.find((collection: CollectionItem) => collection.id === value);
57
- }, [collections, value]);
71
+ if (!collections) return multiple ? [] : undefined;
72
+
73
+ if (multiple && Array.isArray(value)) {
74
+ return collections.filter((collection: CollectionItem) => value.includes(collection.id));
75
+ } else if (!multiple && typeof value === 'string') {
76
+ return collections.find((collection: CollectionItem) => collection.id === value);
77
+ }
78
+ return multiple ? [] : undefined;
79
+ }, [collections, value, multiple]);
58
80
 
59
81
  // Handle collection selection
60
82
  const handleSelect = useCallback((collection: CollectionItem) => {
61
- onChange(collection.id, collection);
62
- }, [onChange]);
83
+ if (multiple) {
84
+ const currentValues = Array.isArray(value) ? value : [];
85
+ const isSelected = currentValues.includes(collection.id);
86
+
87
+ if (isSelected) {
88
+ // Remove from selection
89
+ const newValues = currentValues.filter(id => id !== collection.id);
90
+ const newCollections = collections?.filter(c => newValues.includes(c.id)) || [];
91
+ onChange(newValues, newCollections);
92
+ } else {
93
+ // Add to selection
94
+ const newValues = [...currentValues, collection.id];
95
+ const newCollections = collections?.filter(c => newValues.includes(c.id)) || [];
96
+ onChange(newValues, newCollections);
97
+ }
98
+ } else {
99
+ onChange(collection.id, collection);
100
+ }
101
+ }, [onChange, value, collections, multiple]);
63
102
 
64
103
  // Handle clear selection
65
104
  const handleClear = useCallback(() => {
@@ -71,6 +110,24 @@ export function SelectCollection({ onChange, value, disabled = false, placeholde
71
110
  setSearchQuery(query);
72
111
  }, []);
73
112
 
113
+ const hasSearchQuery = searchQuery.trim().length > 0;
114
+
115
+ // Client-side filtering when not using server search
116
+ const filteredCollections = useMemo(() => {
117
+ if (!collections) return [];
118
+
119
+ // If using server search, collections are already filtered by the server
120
+ if (useServerSearch) return collections;
121
+
122
+ // Otherwise, do client-side filtering
123
+ if (!hasSearchQuery) return collections;
124
+
125
+ const queryLower = searchQuery.toLowerCase();
126
+ return collections.filter(col => col.name.toLowerCase().includes(queryLower));
127
+ }, [collections, useServerSearch, hasSearchQuery, searchQuery]);
128
+
129
+ const showClearOption = selectedCollection && hasSearchQuery;
130
+
74
131
  // Show error state
75
132
  if (error) {
76
133
  return (
@@ -80,8 +137,18 @@ export function SelectCollection({ onChange, value, disabled = false, placeholde
80
137
  );
81
138
  }
82
139
 
83
- const hasSearchQuery = searchQuery.trim().length > 0;
84
- const showClearOption = selectedCollection && hasSearchQuery;
140
+ // Get display text for the button
141
+ const getDisplayText = () => {
142
+ if (multiple && Array.isArray(selectedCollection) && selectedCollection.length > 0) {
143
+ if (selectedCollection.length === 1) {
144
+ return selectedCollection[0].name;
145
+ }
146
+ return `${selectedCollection.length} collections selected`;
147
+ } else if (!multiple && selectedCollection && !Array.isArray(selectedCollection)) {
148
+ return selectedCollection.name;
149
+ }
150
+ return placeholder;
151
+ };
85
152
 
86
153
  return (
87
154
  <Popover>
@@ -94,7 +161,7 @@ export function SelectCollection({ onChange, value, disabled = false, placeholde
94
161
  disabled={disabled}
95
162
  >
96
163
  <span className="truncate flex-1 text-left min-w-0">
97
- {selectedCollection ? selectedCollection.name : placeholder}
164
+ {getDisplayText()}
98
165
  </span>
99
166
  <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
100
167
  </Button>
@@ -125,7 +192,7 @@ export function SelectCollection({ onChange, value, disabled = false, placeholde
125
192
  </CommandEmpty>
126
193
  <CommandGroup className="max-h-[300px] overflow-auto">
127
194
  {
128
- showClearOption && (
195
+ showClearOption && !multiple && (
129
196
  <CommandItem
130
197
  value="__clear__"
131
198
  onSelect={handleClear}
@@ -136,40 +203,29 @@ export function SelectCollection({ onChange, value, disabled = false, placeholde
136
203
  )
137
204
  }
138
205
  {
139
- collections?.map((collection: CollectionItem) => (
140
- <CommandItem
141
- key={collection.id}
142
- value={collection.id}
143
- onSelect={() => handleSelect(collection)}
144
- className={cn(
145
- "flex items-center justify-between",
146
- value === collection.id ? "bg-muted/20" : ""
147
- )}
148
- >
149
- <div className="flex flex-col flex-1 min-w-0">
150
- <span className="truncate font-medium">
151
- {collection.name}
152
- </span>
153
- {
154
- collection.description && (
155
- <span className="text-sm text-muted-foreground truncate">
156
- {collection.description}
157
- </span>
158
- )
159
- }
160
- </div>
161
- <Check
162
- className={cn(
163
- "ml-2 h-4 w-4 shrink-0",
164
- value === collection.id ? "opacity-100" : "opacity-0"
206
+ filteredCollections.map((collection: CollectionItem) => {
207
+ const isSelected = multiple && Array.isArray(value)
208
+ ? value.includes(collection.id)
209
+ : value === collection.id;
210
+
211
+ return (
212
+ <CommandItem
213
+ key={collection.id}
214
+ value={collection.id}
215
+ onSelect={() => handleSelect(collection)}
216
+ className="flex items-center justify-between"
217
+ >
218
+ <span className="truncate">{collection.name}</span>
219
+ {isSelected && (
220
+ <Check className="ml-2 h-4 w-4 shrink-0" />
165
221
  )}
166
- />
167
- </CommandItem>
168
- ))
222
+ </CommandItem>
223
+ );
224
+ })
169
225
  }
170
226
  </CommandGroup>
171
227
  </Command>
172
228
  </PopoverContent>
173
229
  </Popover>
174
230
  );
175
- }
231
+ }
@@ -0,0 +1,61 @@
1
+ import { Collection, ContentObjectType } from "@vertesia/common";
2
+ import { Button, Panel, useToast } from "@vertesia/ui/core";
3
+ import { TagsInput } from "@vertesia/ui/core";
4
+ import { useUserSession } from "@vertesia/ui/session";
5
+ import { useEffect, useState } from "react";
6
+
7
+ interface SharedPropsEditorProps {
8
+ collection: Collection;
9
+ }
10
+ export function SharedPropsEditor({ collection }: SharedPropsEditorProps) {
11
+
12
+ const { client } = useUserSession();
13
+ const [colType, setColType] = useState<ContentObjectType | undefined>(undefined);
14
+ const [sharedProps, setSharedProps] = useState<string[]>(collection.shared_properties || []);
15
+ const toast = useToast();
16
+
17
+ useEffect(() => {
18
+ if (collection.type?.id) {
19
+ client.store.types.retrieve(collection.type.id).then(setColType);
20
+ }
21
+ }, [collection.type?.id]);
22
+
23
+ const options: string[] = colType ? Object.keys(colType.object_schema?.properties || {}) : [];
24
+
25
+ const onSelect = (selected: string[]) => {
26
+ setSharedProps(selected);
27
+ }
28
+
29
+ const onSave = () => {
30
+ client.store.collections.update(collection.id, {
31
+ shared_properties: sharedProps
32
+ }).then(() => {
33
+ // Handle success
34
+ toast({
35
+ title: "Updated shared properties",
36
+ status: "success"
37
+ })
38
+ }).catch((error) => {
39
+ toast({
40
+ title: "Failed to update shared properties",
41
+ description: error.message,
42
+ status: "error"
43
+ })
44
+ // Handle error
45
+ });
46
+ }
47
+
48
+ return (
49
+ <Panel title="Shared Properties" description="Add properties to share across all members in the collection. This feature requires to enable shared property synchronization on the project."
50
+ action={
51
+ <Button size="lg" isLoading={false} onClick={onSave}>
52
+ Save
53
+ </Button>}
54
+ >
55
+ <div className=''>
56
+ <TagsInput value={sharedProps} onChange={onSelect} options={options} placeholder="Select properties to share" />
57
+ </div>
58
+ </Panel>
59
+ )
60
+
61
+ }
@@ -0,0 +1,48 @@
1
+ import { Collection } from "@vertesia/common";
2
+ import { Panel, Switch, useToast } from "@vertesia/ui/core";
3
+ import { useUserSession } from "@vertesia/ui/session";
4
+ import { useState } from "react";
5
+
6
+ interface SyncMemberHeadsToggleProps {
7
+ collection: Collection;
8
+ }
9
+ export function SyncMemberHeadsToggle({ collection }: SyncMemberHeadsToggleProps) {
10
+
11
+ const { client } = useUserSession();
12
+ const [skipHeadSync, setSkipHeadSync] = useState<boolean>(collection.skip_head_sync ?? false);
13
+ const [isSaving, setIsSaving] = useState<boolean>(false);
14
+ const toast = useToast();
15
+
16
+ const onSaveSkipHeadSync = (enableSyncHeads: boolean) => {
17
+ const skip_head_sync = !enableSyncHeads;
18
+ setIsSaving(true);
19
+ client.store.collections.update(collection.id, {
20
+ skip_head_sync: skip_head_sync
21
+ }).then(() => {
22
+ // Handle success
23
+ toast({
24
+ title: "Updated skip head sync setting",
25
+ status: "success"
26
+ })
27
+ setSkipHeadSync(skip_head_sync);
28
+ }).catch((error) => {
29
+ toast({
30
+ title: "Failed to update skip head sync",
31
+ description: error.message,
32
+ status: "error"
33
+ })
34
+ // Handle error
35
+ }).finally(() => {
36
+ setIsSaving(false);
37
+ });
38
+ }
39
+
40
+ return (
41
+ <Panel title="Synchronize Member Heads" description="When a new HEAD version of a member is created the colleciton will be updated to point to the new HEAD.">
42
+ <Switch disabled={isSaving} value={!skipHeadSync} onChange={onSaveSkipHeadSync}>
43
+ Enable synchronizing member heads
44
+ </Switch>
45
+ </Panel>
46
+ )
47
+
48
+ }
@@ -2,4 +2,6 @@ export * from "./BrowseCollectionView";
2
2
  export * from "./CollectionsTable";
3
3
  export * from "./EditCollectionView";
4
4
  export * from "./CreateCollection";
5
- export * from "./SelectCollection";
5
+ export * from "./SelectCollection";
6
+ export * from "./SharedPropsEditor";
7
+ export * from "./SyncMemberHeadsToggle";