@vertesia/ui 0.79.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 (280) 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 +166 -166
  222. package/src/core/components/Panel.tsx +34 -0
  223. package/src/core/components/SidePanel.tsx +5 -3
  224. package/src/core/components/index.ts +1 -1
  225. package/src/core/components/shadcn/breadcrumb.tsx +49 -30
  226. package/src/core/components/shadcn/button.tsx +3 -2
  227. package/src/core/components/shadcn/filters/filterBar.tsx +3 -3
  228. package/src/core/components/shadcn/index.ts +2 -1
  229. package/src/core/components/shadcn/input.tsx +10 -7
  230. package/src/core/components/shadcn/resizeable.tsx +4 -4
  231. package/src/core/components/shadcn/selectBox.tsx +87 -67
  232. package/src/core/components/shadcn/tabs.tsx +10 -3
  233. package/src/core/components/shadcn/textarea.tsx +21 -0
  234. package/src/core/hooks/index.ts +1 -0
  235. package/src/core/hooks/useScrollableSearch.tsx +193 -0
  236. package/src/features/agent/chat/ModernAgentConversation.tsx +109 -118
  237. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +2 -22
  238. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +1 -9
  239. package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +39 -55
  240. package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +1 -0
  241. package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +8 -8
  242. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +8 -8
  243. package/src/features/facets/CollectionsFacetsNav.tsx +21 -0
  244. package/src/features/facets/InteractionsFacetsNav.tsx +13 -3
  245. package/src/features/facets/utils/SearchInterface.tsx +5 -1
  246. package/src/features/facets/utils/VTypeFacet.tsx +6 -2
  247. package/src/features/layout/GenericPageNavHeader.tsx +73 -10
  248. package/src/features/store/collections/BrowseCollectionView.tsx +4 -0
  249. package/src/features/store/collections/CreateCollection.tsx +3 -4
  250. package/src/features/store/collections/EditCollectionView.tsx +91 -85
  251. package/src/features/store/collections/SelectCollection.tsx +105 -49
  252. package/src/features/store/objects/DocumentSearchResults.tsx +117 -51
  253. package/src/features/store/objects/DocumentTable.tsx +14 -4
  254. package/src/features/store/objects/components/ContentOverview.tsx +208 -110
  255. package/src/features/store/objects/components/DocumentIcon.tsx +11 -12
  256. package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +12 -2
  257. package/src/features/store/objects/layout/DocumentTableColumn.tsx +16 -1
  258. package/src/features/store/objects/layout/documentLayout.tsx +7 -5
  259. package/src/features/store/objects/layout/knowledge.md +10 -10
  260. package/src/features/store/objects/layout/renderers.tsx +39 -18
  261. package/src/features/store/objects/search/DocumentSearchContext.ts +6 -1
  262. package/src/features/store/objects/search/DocumentSearchProvider.tsx +1 -1
  263. package/src/features/store/objects/selection/ObjectsActionContext.tsx +3 -2
  264. package/src/features/store/objects/selection/SelectionActions.tsx +2 -0
  265. package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +8 -2
  266. package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +22 -2
  267. package/src/features/store/objects/upload/DocumentUploadModal.tsx +18 -9
  268. package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +10 -7
  269. package/src/features/store/types/CreateOrUpdateTypeModal.tsx +1 -1
  270. package/src/router/HistoryNavigator.ts +33 -2
  271. package/src/router/Nav.tsx +4 -3
  272. package/src/widgets/form/Form.tsx +19 -43
  273. package/src/widgets/form/FormContext.ts +5 -2
  274. package/src/widgets/form/fields.tsx +8 -6
  275. package/src/widgets/form/inputs.tsx +1 -0
  276. package/lib/esm/core/components/Textarea.js +0 -15
  277. package/lib/esm/core/components/Textarea.js.map +0 -1
  278. package/lib/types/core/components/Textarea.d.ts +0 -8
  279. package/lib/types/core/components/Textarea.d.ts.map +0 -1
  280. package/src/core/components/Textarea.tsx +0 -25
@@ -30,8 +30,8 @@ Complete list of supported types:
30
30
  1. **string** - Text display
31
31
  2. **number** - Numeric display
32
32
  3. **date** - Date/time display
33
- 4. **objectLink** - Clickable object reference
34
- 5. **typeLink** - Type reference display
33
+ 4. **objectId** - object id with preview button
34
+ 5. **objectName** - object name display
35
35
 
36
36
  ### Column Types and Renderers
37
37
  Built-in renderers with parameters:
@@ -48,14 +48,14 @@ Built-in renderers with parameters:
48
48
  - `currency`: Format as currency (e.g., USD)
49
49
  - `decimals`: Number of decimal places (default: 2)
50
50
 
51
- 3. **objectLink**
52
- - `title`: Property to use as title (default: "title")
53
- - `underline`: Link underline style (default: "hover")
54
-
55
- 4. **date**
51
+ 3. **date**
56
52
  - `localized`: Use localized format (e.g., "LLL")
57
53
  - `relative`: Use relative time ("fromNow"/"toNow")
58
54
 
55
+ 4. **objectId**
56
+ - `slice`: Take substring from index
57
+
58
+
59
59
  ### Parameter Syntax
60
60
  Parameters are added using URL query string syntax:
61
61
  ```typescript
@@ -92,12 +92,12 @@ Parameters are added using URL query string syntax:
92
92
  {
93
93
  "name": "ID",
94
94
  "field": "id",
95
- "type": "string?slice=-7"
95
+ "type": "objectId?slice=-7"
96
96
  },
97
97
  {
98
98
  "name": "Name",
99
99
  "field": ".",
100
- "type": "objectLink?title=name&underline=always"
100
+ "type": "objectName"
101
101
  },
102
102
  {
103
103
  "name": "Price",
@@ -126,7 +126,7 @@ Parameters are added using URL query string syntax:
126
126
  {
127
127
  "name": "Document",
128
128
  "field": ".",
129
- "type": "objectLink"
129
+ "type": "objectName"
130
130
  },
131
131
  {
132
132
  "name": "Score",
@@ -1,13 +1,14 @@
1
- import { NavLink } from "@vertesia/ui/router";
2
1
  import dayjs from "dayjs";
3
2
  import LocalizedFormat from "dayjs/plugin/localizedFormat";
4
3
  import RelativeTime from "dayjs/plugin/relativeTime";
5
4
  import { shortId } from "../../../utils";
5
+ import { Eye } from "lucide-react";
6
+ import { Button } from "@vertesia/ui/core";
6
7
  dayjs.extend(RelativeTime);
7
8
  dayjs.extend(LocalizedFormat);
8
9
 
9
- const renderers: Record<string, (params?: URLSearchParams) => (value: any, index: number) => React.ReactNode> = {
10
- string(params?: URLSearchParams) {
10
+ const renderers: Record<string, (params?: URLSearchParams, onClick?: (id: string) => void) => (value: any, index: number) => React.ReactNode> = {
11
+ string(params?: URLSearchParams, _onClick?: (id: string) => void) {
11
12
  let transforms: ((value: string) => string)[] = [];
12
13
  if (params) {
13
14
  const slice = params.get("slice");
@@ -48,7 +49,7 @@ const renderers: Record<string, (params?: URLSearchParams) => (value: any, index
48
49
  };
49
50
  },
50
51
 
51
- fileSize(_params?: URLSearchParams) {
52
+ fileSize(_params?: URLSearchParams, _onClick?: (id: string) => void) {
52
53
  return (value: any, index: number) => {
53
54
  let fileSize = "";
54
55
  if (value) {
@@ -69,7 +70,7 @@ const renderers: Record<string, (params?: URLSearchParams) => (value: any, index
69
70
  };
70
71
  },
71
72
 
72
- number(params?: URLSearchParams) {
73
+ number(params?: URLSearchParams, _onClick?: (id: string) => void) {
73
74
  let currency: string | undefined;
74
75
  let decimals: string | undefined;
75
76
  if (params) {
@@ -88,34 +89,54 @@ const renderers: Record<string, (params?: URLSearchParams) => (value: any, index
88
89
  return <td key={index}>{v}</td>;
89
90
  };
90
91
  },
91
- // value must be the object itself
92
- objectLink(params?: URLSearchParams) {
92
+ objectId(params?: URLSearchParams, onClick?: (id: string) => void) {
93
+ let transforms: ((value: string) => string)[] = [];
94
+ let hasSlice = false;
95
+ if (params) {
96
+ const slice = params.get("slice");
97
+ if (slice) {
98
+ hasSlice = true;
99
+ transforms.push((value) => value.slice(parseInt(slice)));
100
+ }
101
+ }
102
+ return (value: any, index: number) => {
103
+ const displayValue = transforms.reduce((v, t) => t(v), value.id);
104
+ return (
105
+ <td key={index} className="flex justify-between items-center gap-2">
106
+ {hasSlice ? '~' : ''}{displayValue}
107
+ <Button
108
+ variant="ghost"
109
+ alt="Preview Object"
110
+ onClick={(e) => {
111
+ e.stopPropagation();
112
+ onClick?.(value.id);
113
+ }}
114
+ >
115
+ <Eye className="size-4" />
116
+ </Button>
117
+ </td>
118
+ );
119
+ };
120
+ },
121
+ objectName(params?: URLSearchParams, _onClick?: (id: string) => void) {
93
122
  let title = "title";
94
- //let underline = "hover";
95
123
  if (params) {
96
124
  title = params.get("title") || "title";
97
- //underline = params.get("underline") || "hover";
98
125
  }
99
126
  return (value: any, index: number) => {
100
127
  return (
101
128
  <td key={index}>
102
- <NavLink
103
- topLevelNav
104
- className="underline text-indigo-800 dark:text-indigo-300"
105
- href={`/store/objects/${value.id}`}
106
- >
107
- {value.properties?.[title] || value.name || shortId(value.id)}
108
- </NavLink>
129
+ {value.properties?.[title] || value.name || shortId(value.id)}
109
130
  </td>
110
131
  );
111
132
  };
112
133
  },
113
- typeLink(_params?: URLSearchParams) {
134
+ typeLink(_params?: URLSearchParams, _onClick?: (id: string) => void) {
114
135
  return (value: any, index: number) => {
115
136
  return <td key={index}>{value?.name || "n/a"}</td>;
116
137
  };
117
138
  },
118
- date(params?: URLSearchParams) {
139
+ date(params?: URLSearchParams, _onClick?: (id: string) => void) {
119
140
  let method = "format";
120
141
  let arg: string | undefined = "LLL";
121
142
  if (params) {
@@ -55,9 +55,13 @@ export class DocumentSearch implements SearchInterface {
55
55
  this.search();
56
56
  }
57
57
 
58
+ setDefaultKeys(keys: any[]) {
59
+ void keys;
60
+ }
61
+
58
62
  clearFilters(autoSearch: boolean = true) {
59
63
  // Preserve search-related fields when clearing filters
60
- const { parent, full_text, vector, weights, score_aggregation, dynamic_scaling, limit } = this.query;
64
+ const { parent, full_text, vector, weights, score_aggregation, dynamic_scaling, limit, all_revisions } = this.query;
61
65
  this.query = {
62
66
  parent,
63
67
  ...(full_text !== undefined && { full_text }),
@@ -65,6 +69,7 @@ export class DocumentSearch implements SearchInterface {
65
69
  ...(weights !== undefined && { weights }),
66
70
  ...(score_aggregation !== undefined && { score_aggregation }),
67
71
  ...(dynamic_scaling !== undefined && { dynamic_scaling }),
72
+ ...(all_revisions !== undefined && { all_revisions }),
68
73
  ...(limit !== undefined && { limit })
69
74
  };
70
75
 
@@ -42,7 +42,7 @@ export function DocumentSearchProvider({ children, limit, parent, typeId, facets
42
42
  search.query.parent = parent;
43
43
  search.query.name = name;
44
44
  return search;
45
- }, [typeId, limit]);
45
+ }, [typeId, limit, collectionId]);
46
46
 
47
47
  return (
48
48
  <SearchContext.Provider value={search}>{children}</SearchContext.Provider>
@@ -6,7 +6,7 @@ import { useUserSession } from '@vertesia/ui/session';
6
6
  import { useDocumentSearch, useDocumentSelection } from '../../../store';
7
7
  import { AddToCollectionAction } from './actions/AddToCollectionAction';
8
8
  import { ChangeTypeAction } from './actions/ChangeTypeAction';
9
- import { DeleteObjectsAction } from './actions/DeleteObjectsAction';
9
+ import { DeleteObjectsAction, DeleteObjectsFromCollectionsAction } from './actions/DeleteObjectsAction';
10
10
  import { ExportPropertiesAction } from './actions/ExportPropertiesAction';
11
11
  import { RemoveFromCollectionAction } from './actions/RemoveFromCollectionAction';
12
12
  import { StartWorkflowAction, StartWorkflowComponent } from './actions/StartWorkflowComponent';
@@ -22,6 +22,7 @@ export class ObjectsActionContext {
22
22
  AddToCollectionAction,
23
23
  DeleteObjectsAction,
24
24
  RemoveFromCollectionAction,
25
+ DeleteObjectsFromCollectionsAction
25
26
  ];
26
27
  wfRules: ObjectsActionSpec[] = [];
27
28
  callbacks: Record<string, ObjectsActionCallback> = {};
@@ -38,7 +39,7 @@ export class ObjectsActionContext {
38
39
  );
39
40
  } else {
40
41
  return this.allActions.filter(action =>
41
- action.id !== 'removeFromCollection'
42
+ action.id !== 'removeFromCollection' && action.id !== 'deleteFromCollections'
42
43
  );
43
44
  }
44
45
  }
@@ -62,6 +62,8 @@ export function UploadObjectsButton({ collectionId }: { collectionId?: string })
62
62
  const selectFile = () => {
63
63
  const fileInput = document.createElement("input");
64
64
  fileInput.type = "file";
65
+ fileInput.multiple = true;
66
+ fileInput.accept = "*";
65
67
  fileInput?.click();
66
68
  fileInput.onchange = (event) => {
67
69
  const files = (event.target as HTMLInputElement).files;
@@ -85,8 +85,14 @@ function AddToCollectionForm({ onClose, objectIds }: AddToCollectionFormProps) {
85
85
  });
86
86
  }
87
87
 
88
- const onCollectionChange = (collectionId: string | undefined) => {
89
- setSelectedCollectionId(collectionId);
88
+ const onCollectionChange = (collectionId: string | string[] | undefined, _collection?: any) => {
89
+ if (typeof collectionId === "string" || typeof collectionId === "undefined") {
90
+ setSelectedCollectionId(collectionId);
91
+ } else if (Array.isArray(collectionId) && collectionId.length > 0) {
92
+ setSelectedCollectionId(collectionId[0]);
93
+ } else {
94
+ setSelectedCollectionId(undefined);
95
+ }
90
96
  };
91
97
 
92
98
  const tabs = [
@@ -28,12 +28,21 @@ export function DeleteObjectsActionComponent({ action, objectIds, children }: Ac
28
28
  return Promise.resolve(false);
29
29
  }
30
30
 
31
+ function limitFilesName(names: string, maxLength: number) {
32
+ if (names.length <= maxLength) return names;
33
+ const extIndex = names.lastIndexOf('.');
34
+ const ext = extIndex !== -1 ? names.substring(extIndex) : '';
35
+ const baseName = extIndex !== -1 ? names.substring(0, extIndex) : names;
36
+ const limitedBaseName = baseName.substring(0, maxLength - ext.length - 3);
37
+ return `${limitedBaseName}...${ext}`;
38
+ }
39
+
31
40
  return Promise.all(objectIds.map(id => client.store.objects.delete(id))).then((res) => {
32
41
  const plural = res.length > 1 ? 's' : '';
33
42
  toast({
34
43
  status: 'success',
35
44
  title: `${res.length} object${plural} deleted`,
36
- description: `Objects ${res.map(d => d.id).join(", ")} have been deleted`,
45
+ description: `Objects ${(limitFilesName(res.map(d => d.id).join(", "), 100))} have been deleted`,
37
46
  duration: 2000
38
47
  });
39
48
 
@@ -71,7 +80,18 @@ export const DeleteObjectsAction: ObjectsActionSpec = {
71
80
  name: 'Delete',
72
81
  description: 'Delete the selected objects',
73
82
  confirm: true,
74
- confirmationText: 'Are you sure you want to delete the selected objects?',
83
+ confirmationText: 'Are you sure you want to delete all the selected objects? This action cannot be undone.',
84
+ component: DeleteObjectsActionComponent,
85
+ destructive: true
86
+ }
87
+
88
+
89
+ export const DeleteObjectsFromCollectionsAction: ObjectsActionSpec = {
90
+ id: 'deleteFromCollections',
91
+ name: 'Delete Objects',
92
+ description: 'Delete the selected objects',
93
+ confirm: true,
94
+ confirmationText: 'Are you sure you want to delete the selected objects?\nThis is not removable from collections.',
75
95
  component: DeleteObjectsActionComponent,
76
96
  destructive: true
77
97
  }
@@ -314,6 +314,7 @@ export function DocumentUploadModal({
314
314
 
315
315
  // Process files in batches of 50
316
316
  const BATCH_SIZE = 50;
317
+ const PROGRESS_UPDATE_INTERVAL = 5; // Update progress every 5 files
317
318
 
318
319
  // Helper function to process a batch of files
319
320
  const processBatch = async (files: FileWithMetadata[], action: "create" | "update") => {
@@ -337,7 +338,8 @@ export function DocumentUploadModal({
337
338
  });
338
339
  }
339
340
 
340
- // Process the batch
341
+ // Process the batch with progress tracking
342
+ let filesProcessedInBatch = 0;
341
343
  await Promise.all(
342
344
  batch.map(async (fileInfo) => {
343
345
  try {
@@ -446,16 +448,23 @@ export function DocumentUploadModal({
446
448
  // Mark the overall success as false if any file fails
447
449
  result.success = false;
448
450
  }
451
+
452
+ // Update progress every PROGRESS_UPDATE_INTERVAL files
453
+ filesProcessedInBatch++;
454
+ if (filesProcessedInBatch % PROGRESS_UPDATE_INTERVAL === 0 || filesProcessedInBatch === batch.length) {
455
+ setFileStatuses((currentStatuses) => {
456
+ const completedFiles = currentStatuses.filter(
457
+ (f) => f.status === "success" || f.status === "error",
458
+ ).length;
459
+ const totalFiles = currentStatuses.length;
460
+ const progress = totalFiles > 0 ? Math.round((completedFiles / totalFiles) * 100) : 0;
461
+ setOverallProgress(progress);
462
+ return currentStatuses;
463
+ });
464
+ }
449
465
  }),
450
466
  );
451
467
 
452
- // Calculate overall progress after each batch completion
453
- const completedFiles = fileStatuses.filter(
454
- (f) => f.status === "success" || f.status === "error",
455
- ).length;
456
- const totalFiles = fileStatuses.length;
457
- const progress = Math.round((completedFiles / totalFiles) * 100);
458
- setOverallProgress(progress);
459
468
  }
460
469
  };
461
470
 
@@ -906,7 +915,7 @@ export function DocumentUploadModal({
906
915
  };
907
916
 
908
917
  return (
909
- <VModal key={modalKey} isOpen={isOpen} onClose={handleClose} className="mx-auto">
918
+ <VModal key={modalKey} isOpen={isOpen} onClose={handleClose} className="mx-auto" disableCloseOnClickOutside>
910
919
  <VModalTitle description={_description}>{_title}</VModalTitle>
911
920
  {renderModalContent()}
912
921
  {renderModalFooter()}
@@ -134,7 +134,10 @@ export function useSmartFileUploadProcessing() {
134
134
 
135
135
  let res: ContentObjectItem[];
136
136
 
137
- const payload: ComplexSearchPayload = {query: {match: query}, select: undefined}
137
+ const payload: ComplexSearchPayload = {
138
+ query: { match: query },
139
+ select: "id content.etag" // Only fetch fields needed for comparison
140
+ };
138
141
 
139
142
  if (limitToCollectionId) {
140
143
  res = (await client.store.collections.searchMembers(limitToCollectionId, payload)).results;
@@ -164,16 +167,16 @@ export function useSmartFileUploadProcessing() {
164
167
  const namesInLocation = unskippedFiles
165
168
  .filter((file) => file.location === location)
166
169
  .map((file) => file.name);
167
- const query = {
168
- location: location ?? "",
170
+ const query: Record<string, any> = {
169
171
  "content.name": { $in: namesInLocation },
172
+ location: location || "/"
170
173
  };
171
174
  if (limitToCollectionId) {
172
175
  const res = client.store.collections.searchMembers(limitToCollectionId, {
173
176
  query: {
174
177
  match: query,
175
178
  },
176
- select: undefined,
179
+ select: "id content.name location" // Only fetch fields needed for comparison
177
180
  }).then((response) => response.results);
178
181
  queries.push(res);
179
182
  } else {
@@ -181,7 +184,7 @@ export function useSmartFileUploadProcessing() {
181
184
  query: {
182
185
  match: query,
183
186
  },
184
- select: undefined,
187
+ select: "id content.name location" // Only fetch fields needed for comparison
185
188
  });
186
189
  queries.push(res);
187
190
  }
@@ -193,10 +196,10 @@ export function useSmartFileUploadProcessing() {
193
196
  //update fileWithMetadata
194
197
  for (const doc of results) {
195
198
  const file = filesWithMetadata.find(
196
- //name must be the same, and location must the same if present and if not, must be empty string
199
+ //name must be the same, and location must match (default is "/")
197
200
  (f) =>
198
201
  f.name === doc.content.name &&
199
- (f.location ? f.location === doc.location : doc.location === ""),
202
+ (f.location ? f.location === doc.location : doc.location === "/"),
200
203
  );
201
204
  if (file) {
202
205
  file.existingId = doc.id;
@@ -48,7 +48,7 @@ export function CreateOrUpdateTypeModal({ title, isOpen, onClose, okLabel, initi
48
48
  </div>
49
49
  <div>
50
50
  <label className="block text-sm font-medium text-muted">Description</label>
51
- <Textarea value={description} onChange={setDescription} />
51
+ <Textarea value={description} onChange={e => setDescription(e.target.value)} />
52
52
  </div>
53
53
  </div>
54
54
  </ModalBody>
@@ -130,10 +130,41 @@ export class HistoryNavigator {
130
130
  if (beforeEvent._canceled) {
131
131
  return;
132
132
  }
133
- window.history[options.replace ? 'replaceState' : 'pushState']({
133
+
134
+ // Build navigation chain by preserving previous history
135
+ const currentState = window.history.state;
136
+ const currentTitle = document.title;
137
+
138
+ // Create new history chain entry
139
+ const newChainEntry = {
140
+ title: currentTitle,
141
+ href: window.location.pathname + window.location.search + window.location.hash
142
+ };
143
+
144
+ // Build the history chain - clear if using replace
145
+ let historyChain: Array<{title: string, href: string}> = [];
146
+ if (!options.replace && currentState?.historyChain) {
147
+ historyChain = [...currentState.historyChain];
148
+ }
149
+
150
+ // Only add to chain if not replacing
151
+ if (!options.replace) {
152
+ historyChain.push(newChainEntry);
153
+
154
+ // Limit chain length to prevent memory issues (keep last 10 entries)
155
+ if (historyChain.length > 10) {
156
+ historyChain = historyChain.slice(-10);
157
+ }
158
+ }
159
+
160
+ const stateToStore = {
134
161
  from: window.location.href,
162
+ historyChain: historyChain,
135
163
  data: options.state || undefined
136
- }, '', to.href);
164
+ };
165
+
166
+ window.history[options.replace ? 'replaceState' : 'pushState'](stateToStore, '', to.href);
167
+
137
168
  this.fireLocationChange(new AfterLocationChangeEvent(type, to, options.state));
138
169
  }
139
170
 
@@ -20,7 +20,7 @@ export function Nav({ children, onClick }: NavProps) {
20
20
  if (link && link.href) {
21
21
  ev.stopPropagation();
22
22
  ev.preventDefault();
23
- navigate(link.href);
23
+ navigate(link.href, { replace: true });
24
24
  onClick?.(ev);
25
25
  }
26
26
  }
@@ -40,14 +40,15 @@ interface NavLinkProps {
40
40
  * use the root router to navigate
41
41
  */
42
42
  topLevelNav?: boolean;
43
+ clearBreadcrumbs?: boolean;
43
44
  }
44
- export function NavLink({ children, href, className, topLevelNav }: NavLinkProps) {
45
+ export function NavLink({ children, href, className, topLevelNav, clearBreadcrumbs = false }: NavLinkProps) {
45
46
  const { router } = useRouterContext();
46
47
  const _onClick = (ev: SyntheticEvent) => {
47
48
  ev.stopPropagation();
48
49
  ev.preventDefault();
49
50
  const actualRouter = topLevelNav ? router.getTopRouter() : router;
50
- actualRouter.navigate(href);
51
+ actualRouter.navigate(href, { replace: clearBreadcrumbs });
51
52
  }
52
53
  return (
53
54
  <a href={href} className={className} onClick={_onClick}>{children}</a>
@@ -1,25 +1,22 @@
1
1
 
2
2
  import { Plus, Trash2 } from "lucide-react";
3
- import { Button } from "@vertesia/ui/core";
3
+ import { Button, FormItem } from "@vertesia/ui/core";
4
4
  import clsx from "clsx";
5
5
  import type { JSONSchemaObject } from "@vertesia/common";
6
6
  import { ComponentType, ReactNode, SyntheticEvent, useState } from "react";
7
- import { FormContextProvider, InputComponentProps, useForm } from "./FormContext.js";
7
+ import { FormContext, FormContextProvider, InputComponentProps, useForm } from "./FormContext.js";
8
8
  import { ManagedListProperty, ManagedObject, ManagedObjectBase, ManagedProperty, Node } from "./ManagedObject.js";
9
- import { FormLabel, FormHelper } from "./fields.js";
10
9
  import { Input } from "./inputs.js";
11
10
 
12
-
13
-
14
-
15
11
  interface FormProps {
16
12
  object: ManagedObject;
17
13
  components?: Record<string, ComponentType<InputComponentProps>>;
18
14
  children?: ReactNode | ReactNode[];
19
15
  onSubmit?: (data: JSONSchemaObject) => void;
20
16
  onChange?: (prop: Node) => void;
17
+ disabled?: boolean;
21
18
  }
22
- export function Form({ object, components, onSubmit, children, onChange }: FormProps) {
19
+ export function Form({ object, components, onSubmit, children, onChange, disabled }: FormProps) {
23
20
  const _onSubmit = (evt: SyntheticEvent) => {
24
21
  evt.stopPropagation();
25
22
  evt.preventDefault();
@@ -27,10 +24,7 @@ export function Form({ object, components, onSubmit, children, onChange }: FormP
27
24
  }
28
25
  object.observer = onChange;
29
26
  return (
30
- <FormContextProvider value={{
31
- object,
32
- components: components || {}
33
- }}>
27
+ <FormContextProvider value={new FormContext(object, components || {}, disabled ?? false)}>
34
28
  <form className="w-full" onSubmit={_onSubmit}>
35
29
  {children}
36
30
  </form>
@@ -58,24 +52,6 @@ export function GeneratedForm({ children, ...props }: FormProps) {
58
52
  )
59
53
  }
60
54
 
61
-
62
- // interface FieldSetProps {
63
- // name: string;
64
- // children?: ReactNode | ReactNode[];
65
- // }
66
- // export function FieldSet({ name, children }: FieldSetProps) {
67
- // const ctx = useForm();
68
- // const newCtx = {
69
- // ...ctx,
70
- // object: ctx.object.getProperty(name) as ManagedObjectProperty
71
- // }
72
- // return (
73
- // <FormContextProvider value={newCtx}>
74
- // {children}
75
- // </FormContextProvider>
76
- // )
77
- // }
78
-
79
55
  function renderProperty(prop: Node) {
80
56
  if (prop.isList) {
81
57
  return <ListField key={prop.name} object={prop as ManagedListProperty} />
@@ -105,7 +81,7 @@ export function ScalarField({ object, editor, inline = false }: ScalarFieldProps
105
81
  if (!editor) {
106
82
  editor = object.schema.editor;
107
83
  }
108
- const { components } = useForm();
84
+ const { components, disabled } = useForm();
109
85
  const Component = (editor && components[editor]) || Input;
110
86
  const inputType = object.getInputType();
111
87
  if (inputType === 'checkbox') {
@@ -113,20 +89,16 @@ export function ScalarField({ object, editor, inline = false }: ScalarFieldProps
113
89
  }
114
90
 
115
91
  const handleOnChange = (event: any) => {
92
+ if (disabled) return;
116
93
  const { value } = event.target;
117
94
  object.value = object.schema.isNumber ? parseFloat(value) : value
118
95
  }
119
96
 
120
97
  return (
121
- <div className="">
122
- <div className={clsx('flex gap-2', inline ? 'flex-row items-center' : 'flex-col')}>
123
- {!object.isListItem && <FormLabel required={object.schema.isRequired}>{object.title}</FormLabel>}
124
- <Component object={object} type={inputType} onChange={handleOnChange} />
125
- </div>
126
- {
127
- object.schema.description && <FormHelper>{object.schema.description}</FormHelper>
128
- }
129
- </div>
98
+ <FormItem label={object.title} required={object.schema.isRequired} description={object.schema.description}
99
+ className={clsx('flex', inline ? 'flex-row items-center' : 'flex-col')}>
100
+ {!object.isListItem && <Component object={object} type={inputType} onChange={handleOnChange} />}
101
+ </FormItem>
130
102
  )
131
103
  }
132
104
 
@@ -149,13 +121,16 @@ interface ListFieldProps {
149
121
  }
150
122
  function ListField({ object }: ListFieldProps) {
151
123
  const [value, setValue] = useState<any[]>(object.value || []);
124
+ const { disabled } = useForm();
152
125
 
153
126
  const addItem = () => {
127
+ if (disabled) return;
154
128
  object.add();
155
129
  setValue([...object.value]);
156
130
  };
157
131
 
158
132
  const deleteItem = (index: number) => {
133
+ if (disabled) return;
159
134
  object.remove(index);
160
135
  setValue([...object.value]);
161
136
  };
@@ -165,11 +140,11 @@ function ListField({ object }: ListFieldProps) {
165
140
  {!object.isListItem && <div className='text-gray-900 dark:text-gray-200 font-semibold'>{object.title}</div>}
166
141
  {
167
142
  object.items.map((item, index) => {
168
- return <ListItem key={`${index}-${value[index] ?? ''}`} object={item} list={object} onDelete={() => deleteItem(index)} />;
143
+ return <ListItem key={`${index}-${value[index] ?? ''}`} object={item} list={object} onDelete={() => deleteItem(index)} disabled={disabled} />;
169
144
  })
170
145
  }
171
146
  <div>
172
- <Button variant='secondary' onClick={addItem}><Plus className="size-6" /> Add</Button>
147
+ <Button variant='secondary' onClick={addItem} disabled={disabled}><Plus className="size-6" /> Add</Button>
173
148
  </div>
174
149
  </div>
175
150
  )
@@ -179,8 +154,9 @@ interface ListItemProps {
179
154
  list: ManagedListProperty;
180
155
  object: Node & { index: number };
181
156
  onDelete: () => void;
157
+ disabled?: boolean;
182
158
  }
183
- function ListItem({ list, object, onDelete }: ListItemProps) {
159
+ function ListItem({ list, object, onDelete, disabled }: ListItemProps) {
184
160
  return (
185
161
  <div className='flex gap-2 w-full'>
186
162
  <div className="flex-1">
@@ -188,7 +164,7 @@ function ListItem({ list, object, onDelete }: ListItemProps) {
188
164
  renderItemProperty(object, list.schema.arraySchema.editor)
189
165
  }
190
166
  </div>
191
- <Button variant='secondary' onClick={onDelete}><Trash2 className='size-4' /></Button>
167
+ <Button variant='secondary' onClick={onDelete} disabled={disabled}><Trash2 className='size-4' /></Button>
192
168
  </div>
193
169
  )
194
170
  }
@@ -15,10 +15,13 @@ export function useFieldSet() {
15
15
  export interface InputComponentProps {
16
16
  object: Node;
17
17
  type: string; // the editor/input type
18
+ onChange?: (event: any) => void;
19
+ disabled?: boolean;
18
20
  }
19
- class FormContext {
21
+ export class FormContext {
20
22
  constructor(public object: ManagedObject,
21
- public components: Record<string, ComponentType<InputComponentProps>> = {}) {
23
+ public components: Record<string, ComponentType<InputComponentProps>> = {},
24
+ public disabled: boolean = false) {
22
25
  }
23
26
 
24
27
  }