@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
@@ -6,8 +6,9 @@ import { useState, useEffect, useRef } from 'react';
6
6
  import { Popover, PopoverContent, PopoverTrigger, PopoverClose } from './popover';
7
7
  import { Command, CommandEmpty, CommandGroup, CommandItem, CommandList } from './command';
8
8
  import { Input } from './input';
9
+ import { Button } from '@vertesia/ui/core';
9
10
 
10
- interface VSelectBoxBaseProps<T> {
11
+ export interface VSelectBoxBaseProps<T> {
11
12
  options: T[] | undefined;
12
13
  optionLabel?: (option: T) => React.ReactNode;
13
14
  onBlur?: () => void;
@@ -23,6 +24,7 @@ interface VSelectBoxBaseProps<T> {
23
24
  popupClass?: string;
24
25
  isClearable?: boolean;
25
26
  border?: boolean;
27
+ inline?: boolean;
26
28
  }
27
29
 
28
30
  interface VSelectBoxSingleProps<T> extends VSelectBoxBaseProps<T> {
@@ -39,7 +41,7 @@ interface VSelectBoxMultipleProps<T> extends VSelectBoxBaseProps<T> {
39
41
 
40
42
  type VSelectBoxProps<T> = VSelectBoxSingleProps<T> | VSelectBoxMultipleProps<T>;
41
43
 
42
- export function VSelectBox<T = any>({ options, optionLabel, value, onChange, addNew, addNewLabel, disabled, filterBy, label, placeholder, className, popupClass, isClearable, border = true, multiple = false, by }: Readonly<VSelectBoxProps<T>>) {
44
+ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, addNew, addNewLabel, disabled, filterBy, label, placeholder, className, popupClass, isClearable, border = true, multiple = false, by, inline = false }: Readonly<VSelectBoxProps<T>>) {
43
45
  const triggerRef = useRef<HTMLDivElement>(null);
44
46
  const [open, setOpen] = useState(false);
45
47
  const [width, setWidth] = useState<number>(0);
@@ -169,6 +171,82 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
169
171
  );
170
172
  };
171
173
 
174
+ // Render the options list content
175
+ const renderOptionsContent = () => (
176
+ <>
177
+ {filterBy && (
178
+ <div className='flex justify-start items-center mb-1'>
179
+ <div className='mx-2'>
180
+ <SearchIcon className="size-4" />
181
+ </div>
182
+ <Input variant='unstyled' value={filterValue} onChange={setFilterValue} className="w-full p-1 rounded-md" placeholder="Search..." />
183
+ </div>
184
+ )}
185
+ <Command className="overflow-hidden">
186
+ <CommandList className={inline ? "max-h-full overflow-y-auto" : "max-h-[200px] overflow-y-auto"}>
187
+ <CommandEmpty>No result found.</CommandEmpty>
188
+ <CommandGroup className="overflow-visible">
189
+ {filteredOptions?.map((opt, index) => {
190
+ const isSelected = multiple
191
+ ? isOptionSelected(opt, Array.isArray(value) ? value : [])
192
+ : value != null ? isOptionsEqual(value as T, opt) : false;
193
+
194
+ return (
195
+ <CommandItem
196
+ key={index}
197
+ onSelect={() => _onClick(opt)}
198
+ className="w-full"
199
+ >
200
+ {multiple || inline ? (
201
+ <div className='w-full flex justify-between items-center cursor-pointer'>
202
+ <div className='w-full truncate text-left'>
203
+ {optionLabel ? optionLabel(opt) : opt as String}
204
+ </div>
205
+ {isSelected && <Check className="size-4" />}
206
+ </div>
207
+ ) : (
208
+ <PopoverClose className='w-full flex justify-between items-center'>
209
+ <div className='w-full truncate text-left'>
210
+ {optionLabel ? optionLabel(opt) : opt as String}
211
+ </div>
212
+ {isSelected && <Check className="size-4" />}
213
+ </PopoverClose>
214
+ )}
215
+ </CommandItem>
216
+ );
217
+ })}
218
+ </CommandGroup>
219
+ </CommandList>
220
+ </Command>
221
+ {addNew && (
222
+ <div className='p-1'>
223
+ <a
224
+ onClick={addNew}
225
+ className={clsx(
226
+ 'gap-x-2 px-2 py-1.5 truncate group flex rounded-md items-center text-sm cursor-pointer hover:bg-accent',
227
+ )}
228
+ >
229
+ <SquarePlus size={16} strokeWidth={1.25} absoluteStrokeWidth />
230
+ {addNewLabel}
231
+ </a>
232
+ </div>
233
+ )}
234
+ </>
235
+ );
236
+
237
+ if (inline) {
238
+ return (
239
+ <div className={clsx(
240
+ className,
241
+ border && 'border border-border rounded-md',
242
+ "bg-popover p-1",
243
+ popupClass
244
+ )}>
245
+ {renderOptionsContent()}
246
+ </div>
247
+ );
248
+ }
249
+
172
250
  return (
173
251
  <Popover>
174
252
  <PopoverTrigger asChild>
@@ -178,7 +256,7 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
178
256
  className={clsx(
179
257
  className,
180
258
  border && 'border border-border',
181
- 'flex flex-row gap-2 items-center justify-between p-2 rounded-md group relative',
259
+ 'flex flex-row gap-2 items-center justify-between p-2 rounded-md group relative [&:hover_.clear-button]:opacity-100',
182
260
  !disabled ? "cursor-pointer hover:bg-muted" : "cursor-not-allowed text-muted",
183
261
  )}
184
262
  >
@@ -194,9 +272,10 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
194
272
  {multiple ? renderMultipleValue() : renderSingleValue()}
195
273
  </div>
196
274
  </div>
197
- <div className="flex items-center gap-1">
275
+ <div className="flex items-center gap-1 group">
198
276
  {isClearable && value && (Array.isArray(value) ? value.length > 0 : true) && (
199
- <div
277
+ <Button variant={"link"} size={"icon"}
278
+ alt="Clear selection"
200
279
  onClick={(e) => {
201
280
  e.stopPropagation();
202
281
  if (multiple) {
@@ -205,10 +284,10 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
205
284
  (onChange as (option: T) => void)(undefined as any);
206
285
  }
207
286
  }}
208
- className="cursor-pointer hover:bg-muted/20 rounded p-1"
287
+ className="cursor-pointer hover:bg-muted/20 clear-button opacity-0 transition-opacity duration-200 rounded p-1"
209
288
  >
210
289
  <X className="size-4" />
211
- </div>
290
+ </Button>
212
291
  )}
213
292
  {!disabled && (
214
293
  <ChevronsUpDown className="size-4 opacity-50" />
@@ -225,66 +304,7 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
225
304
  popupClass
226
305
  )}
227
306
  >
228
- {filterBy && (
229
-
230
- <div className='flex justify-start items-center mb-1'>
231
- <div className='mx-2'>
232
- <SearchIcon className="size-4" />
233
- </div>
234
- <Input variant='unstyled' value={filterValue} onChange={setFilterValue} className="w-full p-1 rounded-md" placeholder="Search..." />
235
- </div>
236
- )}
237
- <Command className="overflow-hidden">
238
- <CommandList className="max-h-[200px] overflow-y-auto">
239
- <CommandEmpty>No result found.</CommandEmpty>
240
- <CommandGroup className="overflow-visible">
241
- {filteredOptions?.map((opt, index) => {
242
- const isSelected = multiple
243
- ? isOptionSelected(opt, Array.isArray(value) ? value : [])
244
- : value != null ? isOptionsEqual(value as T, opt) : false;
245
-
246
- return (
247
- <CommandItem
248
- key={index}
249
- onSelect={() => _onClick(opt)}
250
- className="w-full"
251
- >
252
- {multiple ? (
253
- <div className='w-full flex justify-between items-center cursor-pointer'>
254
- <div className='w-full truncate text-left'>
255
- {optionLabel ? optionLabel(opt) : opt as String}
256
- </div>
257
- {isSelected && <Check className="size-4" />}
258
- </div>
259
- ) : (
260
- <PopoverClose className='w-full flex justify-between items-center'>
261
- <div className='w-full truncate text-left'>
262
- {optionLabel ? optionLabel(opt) : opt as String}
263
- </div>
264
- {isSelected && <Check className="size-4" />}
265
- </PopoverClose>
266
- )}
267
- </CommandItem>
268
- );
269
- })}
270
- </CommandGroup>
271
- </CommandList>
272
- </Command>
273
- {
274
- addNew && (
275
- <div className='p-1'>
276
- <a
277
- onClick={addNew}
278
- className={clsx(
279
- 'gap-x-2 px-2 py-1.5 truncate group flex rounded-md items-center text-sm cursor-pointer hover:bg-accent',
280
- )}
281
- >
282
- <SquarePlus size={16} strokeWidth={1.25} absoluteStrokeWidth />
283
- {addNewLabel}
284
- </a>
285
- </div>
286
- )
287
- }
307
+ {renderOptionsContent()}
288
308
  </PopoverContent>
289
309
  </Popover>
290
310
  );
@@ -106,7 +106,10 @@ const VTabs = ({
106
106
 
107
107
  // Update the URL hash when tab changes (only if updateHash is true and not controlled by parent)
108
108
  if (updateHash && !current) {
109
- window.location.hash = newValue;
109
+ // Preserve existing history state when changing hash
110
+ const currentState = window.history.state;
111
+ const newUrl = window.location.pathname + window.location.search + '#' + newValue;
112
+ window.history.pushState(currentState, '', newUrl);
110
113
  }
111
114
 
112
115
  if (onTabChange) {
@@ -143,7 +146,9 @@ const VTabsBar = ({ className }: { className?: string }) => {
143
146
  const tab = tabs.find(t => t.name === tabName);
144
147
 
145
148
  if (tab?.href && updateHash) {
146
- window.history.pushState(null, '', tab.href);
149
+ // Preserve existing history state when changing tabs
150
+ const currentState = window.history.state;
151
+ window.history.pushState(currentState, '', tab.href);
147
152
  }
148
153
 
149
154
  setTab(tabName);
@@ -236,7 +241,9 @@ const TabsTrigger = React.forwardRef<
236
241
  const handleClick = React.useCallback((event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
237
242
  if (href) {
238
243
  event.preventDefault();
239
- window.history.pushState(null, '', href);
244
+ // Preserve existing history state when changing tabs
245
+ const currentState = window.history.state;
246
+ window.history.pushState(currentState, '', href);
240
247
  }
241
248
  if (props.onClick) {
242
249
  (props.onClick as React.MouseEventHandler<HTMLButtonElement>)(event);
@@ -0,0 +1,21 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "../libs/utils"
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "py-2 text-sm",
11
+ "flex w-full rounded-md border border-input bg-background ring-offset-background",
12
+ "placeholder:text-muted focus-visible:outline-none focus-visible:ring-1 ring-inset focus-visible:ring-ring",
13
+ "disabled:cursor-not-allowed disabled:opacity-50",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ export { Textarea }
@@ -4,17 +4,28 @@ import React, { ReactNode, useContext, useEffect, useState } from "react";
4
4
  //type KeysNotOfType<T, V> = { [K in keyof T]-?: T[K] extends V ? never : K }[keyof T];
5
5
 
6
6
  export class Property<V = any> {
7
- _value?: V;
8
- watchers: ((value: V) => void)[] = [];
9
- constructor(value?: V) {
7
+ private _value?: V;
8
+ private watchers: ((value: V | undefined) => void)[] = [];
9
+ /**
10
+ * Optional name for debugging purposes.
11
+ * When provided, changes to this property will be logged to the console in development mode,
12
+ * making it easier to track state changes and debug reactive updates.
13
+ *
14
+ * Example: new Property<string>('', 'streamingText')
15
+ * Will log: [CompositeState] streamingText: "" → "new value"
16
+ */
17
+ readonly name?: string;
18
+
19
+ constructor(value?: V, name?: string) {
10
20
  this._value = value;
21
+ this.name = name;
11
22
  }
12
23
 
13
24
  get value() {
14
25
  return this._value;
15
26
  }
16
27
 
17
- set value(value: any) {
28
+ set value(value: V | undefined) {
18
29
  if (value !== this._value) {
19
30
  this._value = value;
20
31
  for (const watcher of this.watchers) {
@@ -23,11 +34,11 @@ export class Property<V = any> {
23
34
  }
24
35
  }
25
36
 
26
- watch(watcher: (value: any) => void) {
37
+ watch(watcher: (value: V | undefined) => void) {
27
38
  this.watchers.push(watcher);
28
39
  return () => {
29
40
  this.watchers = this.watchers.filter(w => w !== watcher);
30
- }
41
+ };
31
42
  }
32
43
  }
33
44
 
@@ -140,3 +151,142 @@ export function useDefineSlot(slot: Slot, value: ReactNode | undefined) {
140
151
  }
141
152
  }, [slot, value])
142
153
  }
154
+
155
+ /**
156
+ * Computed property that derives its value from other properties.
157
+ * Automatically recalculates when any of its dependencies change.
158
+ *
159
+ * Think of it like a spreadsheet formula: if cell A1 = 5 and A2 = 10,
160
+ * then A3 = A1 + A2 will automatically update to 15. If A1 changes to 7,
161
+ * A3 automatically becomes 17.
162
+ *
163
+ * @example Basic usage
164
+ * ```typescript
165
+ * class MyState {
166
+ * count = new Property(0, 'count');
167
+ * multiplier = new Property(2, 'multiplier');
168
+ *
169
+ * // Automatically recalculates when count or multiplier changes
170
+ * result = new ComputedProperty(
171
+ * () => (this.count.value || 0) * (this.multiplier.value || 0),
172
+ * [this.count, this.multiplier],
173
+ * 'result'
174
+ * );
175
+ * }
176
+ *
177
+ * state.count.value = 5; // result automatically becomes 10
178
+ * state.multiplier.value = 3; // result automatically becomes 15
179
+ * ```
180
+ *
181
+ * @example Derived state
182
+ * ```typescript
183
+ * class EditorState {
184
+ * workingCopy = new Property<Interaction>();
185
+ * sourceInteraction = new Property<Interaction>();
186
+ *
187
+ * // Automatically true when workingCopy differs from source
188
+ * isDirty = new ComputedProperty(
189
+ * () => JSON.stringify(this.workingCopy.value) !==
190
+ * JSON.stringify(this.sourceInteraction.value),
191
+ * [this.workingCopy, this.sourceInteraction],
192
+ * 'isDirty'
193
+ * );
194
+ * }
195
+ * ```
196
+ *
197
+ * @example Cascading computed properties
198
+ * ```typescript
199
+ * class State {
200
+ * a = new Property(1);
201
+ * b = new Property(2);
202
+ * sum = new ComputedProperty(() => a.value + b.value, [a, b]);
203
+ * doubled = new ComputedProperty(() => sum.value * 2, [sum]);
204
+ * }
205
+ * ```
206
+ *
207
+ * Benefits:
208
+ * - ✅ Automatic updates when dependencies change
209
+ * - ✅ Memoization - only recalculates when needed
210
+ * - ✅ Composable - can depend on other ComputedProperties
211
+ * - ✅ Type-safe with full TypeScript support
212
+ *
213
+ * When to use:
214
+ * - ✅ For derived state (values calculated from other values)
215
+ * - ✅ When dependencies are other Properties or ComputedProperties
216
+ * - ❌ NOT for async operations (use regular methods instead)
217
+ * - ❌ NOT if compute function has side effects
218
+ *
219
+ * @important Remember to call dispose() when the ComputedProperty is no longer needed
220
+ * to prevent memory leaks by unsubscribing from all dependencies.
221
+ */
222
+ export class ComputedProperty<V = any> {
223
+ private _value?: V;
224
+ private watchers: ((value: V | undefined) => void)[] = [];
225
+ private unsubscribers: (() => void)[] = [];
226
+ /**
227
+ * Optional name for debugging purposes.
228
+ * When provided, recalculations will be logged to the console in development mode.
229
+ */
230
+ readonly name?: string;
231
+
232
+ /**
233
+ * @param compute - Function that calculates the derived value
234
+ * @param dependencies - Array of Properties this computed value depends on
235
+ * @param name - Optional name for debugging
236
+ */
237
+ constructor(
238
+ private compute: () => V,
239
+ dependencies: Property<any>[],
240
+ name?: string
241
+ ) {
242
+ this.name = name;
243
+ this.recalculate();
244
+
245
+ // Watch all dependencies - when any changes, recalculate
246
+ for (const dep of dependencies) {
247
+ this.unsubscribers.push(
248
+ dep.watch(() => this.recalculate())
249
+ );
250
+ }
251
+ }
252
+
253
+ private recalculate() {
254
+ const newValue = this.compute();
255
+ if (newValue !== this._value) {
256
+ this._value = newValue;
257
+ for (const watcher of this.watchers) {
258
+ watcher(newValue);
259
+ }
260
+ }
261
+ }
262
+
263
+ get value() {
264
+ return this._value;
265
+ }
266
+
267
+ watch(watcher: (value: V | undefined) => void) {
268
+ this.watchers.push(watcher);
269
+ return () => {
270
+ this.watchers = this.watchers.filter(w => w !== watcher);
271
+ };
272
+ }
273
+
274
+ /**
275
+ * Dispose of this ComputedProperty by unsubscribing from all dependencies.
276
+ * Call this when the ComputedProperty is no longer needed to prevent memory leaks.
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * const computed = new ComputedProperty(...);
281
+ *
282
+ * // Later, when cleaning up:
283
+ * computed.dispose();
284
+ * ```
285
+ */
286
+ dispose() {
287
+ for (const unsub of this.unsubscribers) {
288
+ unsub();
289
+ }
290
+ this.watchers = [];
291
+ }
292
+ }
@@ -11,4 +11,5 @@ export * from "./useFlag.js"
11
11
  export * from "./useIntersectionObserver.js"
12
12
  export * from "./useIsFistRendering.js"
13
13
  export * from "./useSafeLayoutEffect.js"
14
+ export * from "./useScrollableSearch.js"
14
15
  export * from "./useSharedValue.js"
@@ -0,0 +1,193 @@
1
+ import { useIntersectionObserver } from "@vertesia/ui/core";
2
+ import { useEffect, useRef, useState } from "react";
3
+
4
+ interface SearchResponse<ResultT, PageT> {
5
+ /**
6
+ * The search result
7
+ */
8
+ result: ResultT[];
9
+
10
+ /**
11
+ * The next page information or null if no more pages are available
12
+ */
13
+ nextPage: PageT | null;
14
+ }
15
+
16
+ /**
17
+ * The search function signature.
18
+ * @param payload The search payload
19
+ * @param page The information for the page to fetch. Use null to fetch the first page
20
+ * @param pageSize The number of items per page
21
+ * @returns A promise that resolves to the search response
22
+ */
23
+ type SearchFn<PayloadT, ResultT, PageT = number> = (payload: PayloadT, page: PageT | null, pageSize: number) => Promise<SearchResponse<ResultT, PageT>>;
24
+
25
+
26
+ interface ScrollableSearchOptions<ResultT, PayloadT, PageT = number> {
27
+ /**
28
+ * the search function
29
+ */
30
+ search: SearchFn<PayloadT, ResultT, PageT>;
31
+
32
+ /**
33
+ * Initial paylload for the first search
34
+ */
35
+ payload: PayloadT;
36
+
37
+ /**
38
+ * Which page size to use. Defaults to 50.
39
+ */
40
+ pageSize?: number;
41
+
42
+ /**
43
+ * A ref to the element that triggers loading the next page when it enters the viewport
44
+ */
45
+ nextPageTrigger: React.RefObject<HTMLElement | null>;
46
+ }
47
+
48
+ interface ScrollableSearchResult<ResultT, PayloadT, PageT = number> {
49
+ /**
50
+ * Initiates a new search with the given payload
51
+ * @param payload The search payload
52
+ */
53
+ search: (payload: PayloadT) => void;
54
+
55
+ /**
56
+ * Refreshes the current search with the last used payload
57
+ */
58
+ refresh: () => void;
59
+
60
+ /**
61
+ * Loads the next page of results
62
+ */
63
+ searchMore: () => void;
64
+
65
+ /**
66
+ * The current accumulated search result
67
+ */
68
+ result: ResultT[];
69
+
70
+ /**
71
+ * The current page information
72
+ */
73
+ page: PageT | null;
74
+
75
+ /**
76
+ * Whether there are more pages to load
77
+ */
78
+ hasMore: boolean;
79
+
80
+ /**
81
+ * Any error that occurred during the last search
82
+ */
83
+ error: Error | null;
84
+
85
+ /**
86
+ * Whether a search is currently in progress
87
+ */
88
+ isSearching: boolean;
89
+ }
90
+
91
+ /**
92
+ * A hook that provides paginated search functionality with infinite scrolling support.
93
+ */
94
+ export function useScrollableSearch<ResultT, PayloadT, PageT = number>(opts: ScrollableSearchOptions<ResultT, PayloadT, PageT>, dependencies: any[] = []): ScrollableSearchResult<ResultT, PayloadT, PageT> {
95
+ const pageSize = opts.pageSize || 50;
96
+ const [page, setPage] = useState<PageT | null>(null);
97
+ const [lastPayload, setLastPayload] = useState<PayloadT>(opts.payload);
98
+ const [error, setError] = useState<Error | null>(null);
99
+ const [results, setResults] = useState<ResultT[]>([]);
100
+ const [nextPage, setNextPage] = useState<PageT | null>(null);
101
+ const [isSearching, setIsSearching] = useState(false);
102
+
103
+ // Track current request to prevent stale results
104
+ const requestIdRef = useRef(0);
105
+
106
+ const search = (payload: PayloadT) => {
107
+ setPage(null);
108
+ setResults([]); // Clear old results immediately
109
+ setNextPage(null);
110
+ setLastPayload(payload);
111
+ }
112
+
113
+ const searchMore = () => {
114
+ if (nextPage !== null) {
115
+ setPage(nextPage);
116
+ }
117
+ }
118
+
119
+ useEffect(() => {
120
+ // Increment request ID to mark previous requests as stale
121
+ requestIdRef.current += 1;
122
+ const currentRequestId = requestIdRef.current;
123
+
124
+ setIsSearching(true);
125
+ opts.search(lastPayload, page, pageSize).then(r => {
126
+ // Only update state if this is still the current request
127
+ if (currentRequestId !== requestIdRef.current) {
128
+ return; // Stale request, ignore results
129
+ }
130
+
131
+ // If page is null, it's a new search - replace results
132
+ // Otherwise, it's loading more - append results
133
+ if (page === null) {
134
+ setResults(r.result);
135
+ } else {
136
+ setResults(prev => [...prev, ...r.result]);
137
+ }
138
+ setNextPage(r.nextPage);
139
+ setError(null);
140
+ }).catch(error => {
141
+ // Only update error if this is still the current request
142
+ if (currentRequestId !== requestIdRef.current) {
143
+ return; // Stale request, ignore error
144
+ }
145
+ setError(error);
146
+ }).finally(() => {
147
+ // Only update isSearching if this is still the current request
148
+ if (currentRequestId === requestIdRef.current) {
149
+ setIsSearching(false);
150
+ }
151
+ });
152
+ }, [...dependencies, lastPayload, page]);
153
+
154
+ // Intersection observer for infinite scrolling
155
+ useIntersectionObserver(opts.nextPageTrigger, () => {
156
+ if (!isSearching && nextPage) {
157
+ searchMore();
158
+ }
159
+ }, { threshold: 0.1, deps: [nextPage, isSearching] });
160
+
161
+ return {
162
+ search,
163
+ refresh: () => search(lastPayload),
164
+ searchMore,
165
+ result: results,
166
+ page,
167
+ hasMore: nextPage !== null,
168
+ error,
169
+ isSearching,
170
+ }
171
+ }
172
+
173
+ type DefaultSearchFn<PayloadT, ResultT> = (payload: PayloadT, offset: number, limit: number) => Promise<ResultT[]>;
174
+
175
+ interface DefaultScrollableSearchOptions<ResultT, PayloadT> extends Omit<ScrollableSearchOptions<ResultT, PayloadT, number>, 'search'> {
176
+ search: DefaultSearchFn<PayloadT, ResultT>;
177
+ }
178
+
179
+ export function useDefaultScrollableSearch<ResultT, PayloadT>(opts: DefaultScrollableSearchOptions<ResultT, PayloadT>, dependencies: any[] = []): ScrollableSearchResult<ResultT, PayloadT, number> {
180
+ const actualOpts: ScrollableSearchOptions<ResultT, PayloadT, number> = {
181
+ ...opts,
182
+ async search(payload, page, pageSize) {
183
+ const currentPage = page ?? 0;
184
+ const offset = currentPage * pageSize;
185
+ const result = await opts.search(payload, offset, pageSize);
186
+ return {
187
+ result,
188
+ nextPage: result.length === 0 ? null : currentPage + 1
189
+ };
190
+ }
191
+ };
192
+ return useScrollableSearch<ResultT, PayloadT, number>(actualOpts, dependencies);
193
+ }
package/src/env/index.ts CHANGED
@@ -12,6 +12,7 @@ export interface EnvProps {
12
12
  endpoints: {
13
13
  zeno: string,
14
14
  studio: string,
15
+ sts: string, // Security Token Service endpoint
15
16
  },
16
17
  firebase?: {
17
18
  apiKey: string,
@@ -20,7 +21,7 @@ export interface EnvProps {
20
21
  appId?: string,
21
22
  providerType?: string,
22
23
  },
23
- datadog: boolean,
24
+ datadog?: boolean,
24
25
  logger?: {
25
26
  info: (msg: string, ...args: any) => void,
26
27
  warn: (msg: string, ...args: any) => void,
@@ -93,7 +94,7 @@ export class VertesiaEnvironment implements Readonly<EnvProps> {
93
94
  }
94
95
 
95
96
  get datadog() {
96
- return this.prop("datadog");
97
+ return this._props?.datadog ?? false;
97
98
  }
98
99
 
99
100
  get logger() {
@@ -117,4 +118,4 @@ export class VertesiaEnvironment implements Readonly<EnvProps> {
117
118
 
118
119
  const Env = new VertesiaEnvironment();
119
120
 
120
- export { Env };
121
+ export { Env };