@databiosphere/findable-ui 49.0.0 → 49.2.0

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 (315) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/lib/common/ai/config/types.d.ts +22 -0
  4. package/lib/common/ai/config/types.js +1 -0
  5. package/lib/common/ai/constants.d.ts +3 -0
  6. package/lib/common/ai/constants.js +3 -0
  7. package/lib/components/Filter/components/FilterLabel/filterLabel.js +1 -1
  8. package/lib/components/Filter/components/FilterLabel/filterLabel.stories.d.ts +3 -0
  9. package/lib/components/Filter/components/FilterLabel/filterLabel.stories.js +5 -0
  10. package/lib/components/Filter/components/Filters/stories/constants.js +21 -1
  11. package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.styles.js +2 -0
  12. package/lib/components/Layout/components/Sidebar/components/SidebarTools/sidebarTools.styles.d.ts +4 -0
  13. package/lib/components/Layout/components/Sidebar/components/SidebarTools/sidebarTools.styles.js +4 -0
  14. package/lib/components/common/Chip/components/Beta/beta.d.ts +10 -0
  15. package/lib/components/common/Chip/components/Beta/beta.js +12 -0
  16. package/lib/components/common/Chip/components/Beta/beta.styles.d.ts +3 -0
  17. package/lib/components/common/Chip/components/Beta/beta.styles.js +14 -0
  18. package/lib/components/common/Chip/components/Beta/stories/beta.stories.d.ts +6 -0
  19. package/lib/components/common/Chip/components/Beta/stories/beta.stories.js +6 -0
  20. package/lib/components/common/CustomIcon/components/UpArrowIcon/upArrowIcon.d.ts +6 -0
  21. package/lib/components/common/CustomIcon/components/UpArrowIcon/upArrowIcon.js +8 -0
  22. package/lib/components/common/Tabs/tabs.js +1 -1
  23. package/lib/components/common/ToggleButtonGroup/provider/context.d.ts +2 -0
  24. package/lib/components/common/ToggleButtonGroup/provider/context.js +5 -0
  25. package/lib/components/common/ToggleButtonGroup/provider/hook.d.ts +7 -0
  26. package/lib/components/common/ToggleButtonGroup/provider/hook.js +9 -0
  27. package/lib/components/common/ToggleButtonGroup/provider/provider.d.ts +12 -0
  28. package/lib/components/common/ToggleButtonGroup/provider/provider.js +22 -0
  29. package/lib/components/common/ToggleButtonGroup/provider/types.d.ts +9 -0
  30. package/lib/components/common/ToggleButtonGroup/provider/types.js +1 -0
  31. package/lib/config/entities.d.ts +2 -0
  32. package/lib/hooks/ai/useAiRoutes/hook.d.ts +6 -0
  33. package/lib/hooks/ai/useAiRoutes/hook.js +18 -0
  34. package/lib/styles/common/mui/drawer.d.ts +9 -0
  35. package/lib/styles/common/mui/drawer.js +15 -0
  36. package/lib/styles/common/mui/inputBase.d.ts +13 -0
  37. package/lib/styles/common/mui/inputBase.js +25 -0
  38. package/lib/styles/common/mui/stack.d.ts +11 -0
  39. package/lib/styles/common/mui/stack.js +22 -0
  40. package/lib/tests/testIds.d.ts +3 -0
  41. package/lib/tests/testIds.js +3 -0
  42. package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.d.ts +6 -0
  43. package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.js +17 -0
  44. package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.styles.d.ts +6 -0
  45. package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.styles.js +23 -0
  46. package/lib/views/ExploreView/entityList/filters/filters.styles.d.ts +7 -0
  47. package/lib/views/ExploreView/entityList/filters/filters.styles.js +17 -0
  48. package/lib/views/ExploreView/exploreView.js +3 -2
  49. package/lib/views/ResearchView/assistant/assistant.d.ts +6 -0
  50. package/lib/views/ResearchView/assistant/assistant.js +16 -0
  51. package/lib/views/ResearchView/assistant/components/Drawer/drawer.d.ts +9 -0
  52. package/lib/views/ResearchView/assistant/components/Drawer/drawer.js +15 -0
  53. package/lib/views/ResearchView/assistant/components/Drawer/drawer.styles.d.ts +4 -0
  54. package/lib/views/ResearchView/assistant/components/Drawer/drawer.styles.js +21 -0
  55. package/lib/views/ResearchView/assistant/components/Drawer/types.d.ts +4 -0
  56. package/lib/views/ResearchView/assistant/components/Drawer/types.js +1 -0
  57. package/lib/views/ResearchView/assistant/components/Form/constants.d.ts +3 -0
  58. package/lib/views/ResearchView/assistant/components/Form/constants.js +3 -0
  59. package/lib/views/ResearchView/assistant/components/Form/form.d.ts +11 -0
  60. package/lib/views/ResearchView/assistant/components/Form/form.js +27 -0
  61. package/lib/views/ResearchView/assistant/components/Form/form.styles.d.ts +4 -0
  62. package/lib/views/ResearchView/assistant/components/Form/form.styles.js +7 -0
  63. package/lib/views/ResearchView/assistant/components/Form/types.d.ts +3 -0
  64. package/lib/views/ResearchView/assistant/components/Form/types.js +1 -0
  65. package/lib/views/ResearchView/assistant/components/Form/utils.d.ts +16 -0
  66. package/lib/views/ResearchView/assistant/components/Form/utils.js +41 -0
  67. package/lib/views/ResearchView/assistant/components/Input/constants.d.ts +2 -0
  68. package/lib/views/ResearchView/assistant/components/Input/constants.js +14 -0
  69. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/constants.d.ts +7 -0
  70. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/constants.js +7 -0
  71. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/hook.d.ts +6 -0
  72. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/hook.js +32 -0
  73. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/types.d.ts +8 -0
  74. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/types.js +1 -0
  75. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/utils.d.ts +32 -0
  76. package/lib/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/utils.js +74 -0
  77. package/lib/views/ResearchView/assistant/components/Input/input.d.ts +9 -0
  78. package/lib/views/ResearchView/assistant/components/Input/input.js +19 -0
  79. package/lib/views/ResearchView/assistant/components/Input/input.styles.d.ts +8 -0
  80. package/lib/views/ResearchView/assistant/components/Input/input.styles.js +19 -0
  81. package/lib/views/ResearchView/assistant/components/Input/stories/input.stories.d.ts +6 -0
  82. package/lib/views/ResearchView/assistant/components/Input/stories/input.stories.js +11 -0
  83. package/lib/views/ResearchView/assistant/components/Input/types.d.ts +2 -0
  84. package/lib/views/ResearchView/assistant/components/Input/types.js +1 -0
  85. package/lib/views/ResearchView/assistant/components/Input/utils.d.ts +9 -0
  86. package/lib/views/ResearchView/assistant/components/Input/utils.js +25 -0
  87. package/lib/views/ResearchView/assistant/components/Messages/components/AssistantMessage/assistantMessage.d.ts +9 -0
  88. package/lib/views/ResearchView/assistant/components/Messages/components/AssistantMessage/assistantMessage.js +15 -0
  89. package/lib/views/ResearchView/assistant/components/Messages/components/AssistantMessage/types.d.ts +4 -0
  90. package/lib/views/ResearchView/assistant/components/Messages/components/AssistantMessage/types.js +1 -0
  91. package/lib/views/ResearchView/assistant/components/Messages/components/AssistantMessage/utils.d.ts +13 -0
  92. package/lib/views/ResearchView/assistant/components/Messages/components/AssistantMessage/utils.js +25 -0
  93. package/lib/views/ResearchView/assistant/components/Messages/components/ErrorMessage/errorMessage.d.ts +9 -0
  94. package/lib/views/ResearchView/assistant/components/Messages/components/ErrorMessage/errorMessage.js +12 -0
  95. package/lib/views/ResearchView/assistant/components/Messages/components/ErrorMessage/types.d.ts +4 -0
  96. package/lib/views/ResearchView/assistant/components/Messages/components/ErrorMessage/types.js +1 -0
  97. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/chips.d.ts +3 -0
  98. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/chips.js +10 -0
  99. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/chips.styles.d.ts +3 -0
  100. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/chips.styles.js +26 -0
  101. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/types.d.ts +5 -0
  102. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/types.js +1 -0
  103. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/promptMessage.d.ts +10 -0
  104. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/promptMessage.js +14 -0
  105. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/types.d.ts +5 -0
  106. package/lib/views/ResearchView/assistant/components/Messages/components/PromptMessage/types.js +1 -0
  107. package/lib/views/ResearchView/assistant/components/Messages/components/UserMessage/types.d.ts +4 -0
  108. package/lib/views/ResearchView/assistant/components/Messages/components/UserMessage/types.js +1 -0
  109. package/lib/views/ResearchView/assistant/components/Messages/components/UserMessage/useMessage.styles.d.ts +5 -0
  110. package/lib/views/ResearchView/assistant/components/Messages/components/UserMessage/useMessage.styles.js +10 -0
  111. package/lib/views/ResearchView/assistant/components/Messages/components/UserMessage/userMessage.d.ts +9 -0
  112. package/lib/views/ResearchView/assistant/components/Messages/components/UserMessage/userMessage.js +13 -0
  113. package/lib/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.d.ts +8 -0
  114. package/lib/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.js +20 -0
  115. package/lib/views/ResearchView/assistant/components/Messages/messages.d.ts +9 -0
  116. package/lib/views/ResearchView/assistant/components/Messages/messages.js +16 -0
  117. package/lib/views/ResearchView/assistant/components/Messages/messages.styles.d.ts +3 -0
  118. package/lib/views/ResearchView/assistant/components/Messages/messages.styles.js +9 -0
  119. package/lib/views/ResearchView/assistant/components/Messages/selector/messageSelector.d.ts +17 -0
  120. package/lib/views/ResearchView/assistant/components/Messages/selector/messageSelector.js +32 -0
  121. package/lib/views/ResearchView/assistant/components/Messages/selector/types.d.ts +5 -0
  122. package/lib/views/ResearchView/assistant/components/Messages/selector/types.js +1 -0
  123. package/lib/views/ResearchView/assistant/components/Messages/stories/args.d.ts +3 -0
  124. package/lib/views/ResearchView/assistant/components/Messages/stories/args.js +109 -0
  125. package/lib/views/ResearchView/assistant/components/Messages/stories/messages.stories.d.ts +6 -0
  126. package/lib/views/ResearchView/assistant/components/Messages/stories/messages.stories.js +14 -0
  127. package/lib/views/ResearchView/assistant/components/Messages/types.d.ts +4 -0
  128. package/lib/views/ResearchView/assistant/components/Messages/types.js +1 -0
  129. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/stories/toggleButtonGroup.stories.d.ts +6 -0
  130. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/stories/toggleButtonGroup.stories.js +12 -0
  131. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.d.ts +6 -0
  132. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.js +16 -0
  133. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.styles.d.ts +6 -0
  134. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.styles.js +20 -0
  135. package/lib/views/ResearchView/assistant/stories/args.d.ts +4 -0
  136. package/lib/views/ResearchView/assistant/stories/args.js +30 -0
  137. package/lib/views/ResearchView/assistant/stories/assistant.stories.d.ts +6 -0
  138. package/lib/views/ResearchView/assistant/stories/assistant.stories.js +23 -0
  139. package/lib/views/ResearchView/query/constants.d.ts +5 -0
  140. package/lib/views/ResearchView/query/constants.js +5 -0
  141. package/lib/views/ResearchView/query/fetch.d.ts +17 -0
  142. package/lib/views/ResearchView/query/fetch.js +44 -0
  143. package/lib/views/ResearchView/researchView.d.ts +10 -0
  144. package/lib/views/ResearchView/researchView.js +13 -0
  145. package/lib/views/ResearchView/state/actions/setError/action.d.ts +10 -0
  146. package/lib/views/ResearchView/state/actions/setError/action.js +17 -0
  147. package/lib/views/ResearchView/state/actions/setError/dispatch.d.ts +7 -0
  148. package/lib/views/ResearchView/state/actions/setError/dispatch.js +12 -0
  149. package/lib/views/ResearchView/state/actions/setError/types.d.ts +14 -0
  150. package/lib/views/ResearchView/state/actions/setError/types.js +1 -0
  151. package/lib/views/ResearchView/state/actions/setMessage/action.d.ts +10 -0
  152. package/lib/views/ResearchView/state/actions/setMessage/action.js +21 -0
  153. package/lib/views/ResearchView/state/actions/setMessage/dispatch.d.ts +7 -0
  154. package/lib/views/ResearchView/state/actions/setMessage/dispatch.js +12 -0
  155. package/lib/views/ResearchView/state/actions/setMessage/types.d.ts +15 -0
  156. package/lib/views/ResearchView/state/actions/setMessage/types.js +1 -0
  157. package/lib/views/ResearchView/state/actions/setQuery/action.d.ts +10 -0
  158. package/lib/views/ResearchView/state/actions/setQuery/action.js +17 -0
  159. package/lib/views/ResearchView/state/actions/setQuery/dispatch.d.ts +7 -0
  160. package/lib/views/ResearchView/state/actions/setQuery/dispatch.js +12 -0
  161. package/lib/views/ResearchView/state/actions/setQuery/types.d.ts +14 -0
  162. package/lib/views/ResearchView/state/actions/setQuery/types.js +1 -0
  163. package/lib/views/ResearchView/state/actions/setStatus/action.d.ts +10 -0
  164. package/lib/views/ResearchView/state/actions/setStatus/action.js +13 -0
  165. package/lib/views/ResearchView/state/actions/setStatus/dispatch.d.ts +7 -0
  166. package/lib/views/ResearchView/state/actions/setStatus/dispatch.js +12 -0
  167. package/lib/views/ResearchView/state/actions/setStatus/types.d.ts +14 -0
  168. package/lib/views/ResearchView/state/actions/setStatus/types.js +1 -0
  169. package/lib/views/ResearchView/state/actions/types.d.ts +17 -0
  170. package/lib/views/ResearchView/state/actions/types.js +10 -0
  171. package/lib/views/ResearchView/state/constants.d.ts +5 -0
  172. package/lib/views/ResearchView/state/constants.js +7 -0
  173. package/lib/views/ResearchView/state/context.d.ts +5 -0
  174. package/lib/views/ResearchView/state/context.js +9 -0
  175. package/lib/views/ResearchView/state/guards/guards.d.ts +33 -0
  176. package/lib/views/ResearchView/state/guards/guards.js +41 -0
  177. package/lib/views/ResearchView/state/hooks/UseChatDispatch/hook.d.ts +6 -0
  178. package/lib/views/ResearchView/state/hooks/UseChatDispatch/hook.js +26 -0
  179. package/lib/views/ResearchView/state/hooks/UseChatDispatch/types.d.ts +10 -0
  180. package/lib/views/ResearchView/state/hooks/UseChatDispatch/types.js +1 -0
  181. package/lib/views/ResearchView/state/hooks/UseChatReducer/hook.d.ts +8 -0
  182. package/lib/views/ResearchView/state/hooks/UseChatReducer/hook.js +12 -0
  183. package/lib/views/ResearchView/state/hooks/UseChatState/hook.d.ts +7 -0
  184. package/lib/views/ResearchView/state/hooks/UseChatState/hook.js +11 -0
  185. package/lib/views/ResearchView/state/initializer/initializer.d.ts +8 -0
  186. package/lib/views/ResearchView/state/initializer/initializer.js +22 -0
  187. package/lib/views/ResearchView/state/initializer/types.d.ts +2 -0
  188. package/lib/views/ResearchView/state/initializer/types.js +1 -0
  189. package/lib/views/ResearchView/state/provider.d.ts +19 -0
  190. package/lib/views/ResearchView/state/provider.js +20 -0
  191. package/lib/views/ResearchView/state/query/context.d.ts +5 -0
  192. package/lib/views/ResearchView/state/query/context.js +7 -0
  193. package/lib/views/ResearchView/state/query/hooks/UseQuery/hook.d.ts +6 -0
  194. package/lib/views/ResearchView/state/query/hooks/UseQuery/hook.js +9 -0
  195. package/lib/views/ResearchView/state/query/hooks/UseSubmit/hook.d.ts +7 -0
  196. package/lib/views/ResearchView/state/query/hooks/UseSubmit/hook.js +46 -0
  197. package/lib/views/ResearchView/state/query/provider.d.ts +13 -0
  198. package/lib/views/ResearchView/state/query/provider.js +15 -0
  199. package/lib/views/ResearchView/state/query/types.d.ts +24 -0
  200. package/lib/views/ResearchView/state/query/types.js +1 -0
  201. package/lib/views/ResearchView/state/reducer.d.ts +10 -0
  202. package/lib/views/ResearchView/state/reducer.js +32 -0
  203. package/lib/views/ResearchView/state/types.d.ts +125 -0
  204. package/lib/views/ResearchView/state/types.js +22 -0
  205. package/package.json +1 -1
  206. package/src/common/ai/config/types.ts +25 -0
  207. package/src/common/ai/constants.ts +3 -0
  208. package/src/components/Filter/components/FilterLabel/filterLabel.stories.tsx +6 -0
  209. package/src/components/Filter/components/FilterLabel/filterLabel.tsx +6 -1
  210. package/src/components/Filter/components/Filters/stories/constants.ts +25 -1
  211. package/src/components/Filter/components/SearchAllFilters/searchAllFilters.styles.ts +2 -0
  212. package/src/components/Layout/components/Sidebar/components/SidebarTools/sidebarTools.styles.ts +4 -0
  213. package/src/components/common/Chip/components/Beta/beta.styles.ts +15 -0
  214. package/src/components/common/Chip/components/Beta/beta.tsx +25 -0
  215. package/src/components/common/Chip/components/Beta/stories/beta.stories.tsx +12 -0
  216. package/src/components/common/CustomIcon/components/UpArrowIcon/upArrowIcon.tsx +21 -0
  217. package/src/components/common/Tabs/tabs.tsx +5 -1
  218. package/src/components/common/ToggleButtonGroup/provider/context.ts +9 -0
  219. package/src/components/common/ToggleButtonGroup/provider/hook.ts +16 -0
  220. package/src/components/common/ToggleButtonGroup/provider/provider.tsx +37 -0
  221. package/src/components/common/ToggleButtonGroup/provider/types.ts +17 -0
  222. package/src/config/entities.ts +2 -0
  223. package/src/hooks/ai/useAiRoutes/hook.ts +22 -0
  224. package/src/styles/common/mui/drawer.ts +24 -0
  225. package/src/styles/common/mui/inputBase.ts +38 -0
  226. package/src/styles/common/mui/stack.ts +33 -0
  227. package/src/tests/testIds.ts +3 -0
  228. package/src/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.styles.ts +25 -0
  229. package/src/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.tsx +35 -0
  230. package/src/views/ExploreView/entityList/filters/filters.styles.ts +19 -0
  231. package/src/views/ExploreView/exploreView.tsx +16 -12
  232. package/src/views/ResearchView/assistant/assistant.tsx +28 -0
  233. package/src/views/ResearchView/assistant/components/Drawer/drawer.styles.ts +24 -0
  234. package/src/views/ResearchView/assistant/components/Drawer/drawer.tsx +26 -0
  235. package/src/views/ResearchView/assistant/components/Drawer/types.ts +5 -0
  236. package/src/views/ResearchView/assistant/components/Form/constants.ts +3 -0
  237. package/src/views/ResearchView/assistant/components/Form/form.styles.ts +8 -0
  238. package/src/views/ResearchView/assistant/components/Form/form.tsx +40 -0
  239. package/src/views/ResearchView/assistant/components/Form/types.ts +9 -0
  240. package/src/views/ResearchView/assistant/components/Form/utils.ts +51 -0
  241. package/src/views/ResearchView/assistant/components/Input/constants.ts +16 -0
  242. package/src/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/constants.ts +7 -0
  243. package/src/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/hook.ts +45 -0
  244. package/src/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/types.ts +10 -0
  245. package/src/views/ResearchView/assistant/components/Input/hooks/UseKeyShortCuts/utils.ts +93 -0
  246. package/src/views/ResearchView/assistant/components/Input/input.styles.ts +21 -0
  247. package/src/views/ResearchView/assistant/components/Input/input.tsx +37 -0
  248. package/src/views/ResearchView/assistant/components/Input/stories/input.stories.tsx +21 -0
  249. package/src/views/ResearchView/assistant/components/Input/types.ts +3 -0
  250. package/src/views/ResearchView/assistant/components/Input/utils.ts +34 -0
  251. package/src/views/ResearchView/assistant/components/Messages/components/AssistantMessage/assistantMessage.tsx +49 -0
  252. package/src/views/ResearchView/assistant/components/Messages/components/AssistantMessage/types.ts +5 -0
  253. package/src/views/ResearchView/assistant/components/Messages/components/AssistantMessage/utils.ts +31 -0
  254. package/src/views/ResearchView/assistant/components/Messages/components/ErrorMessage/errorMessage.tsx +21 -0
  255. package/src/views/ResearchView/assistant/components/Messages/components/ErrorMessage/types.ts +5 -0
  256. package/src/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/chips.styles.ts +27 -0
  257. package/src/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/chips.tsx +31 -0
  258. package/src/views/ResearchView/assistant/components/Messages/components/PromptMessage/components/Chips/types.ts +6 -0
  259. package/src/views/ResearchView/assistant/components/Messages/components/PromptMessage/promptMessage.tsx +26 -0
  260. package/src/views/ResearchView/assistant/components/Messages/components/PromptMessage/types.ts +6 -0
  261. package/src/views/ResearchView/assistant/components/Messages/components/UserMessage/types.ts +5 -0
  262. package/src/views/ResearchView/assistant/components/Messages/components/UserMessage/useMessage.styles.ts +11 -0
  263. package/src/views/ResearchView/assistant/components/Messages/components/UserMessage/userMessage.tsx +21 -0
  264. package/src/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.ts +25 -0
  265. package/src/views/ResearchView/assistant/components/Messages/messages.styles.ts +10 -0
  266. package/src/views/ResearchView/assistant/components/Messages/messages.tsx +29 -0
  267. package/src/views/ResearchView/assistant/components/Messages/selector/messageSelector.tsx +37 -0
  268. package/src/views/ResearchView/assistant/components/Messages/selector/types.ts +6 -0
  269. package/src/views/ResearchView/assistant/components/Messages/stories/args.ts +115 -0
  270. package/src/views/ResearchView/assistant/components/Messages/stories/messages.stories.tsx +24 -0
  271. package/src/views/ResearchView/assistant/components/Messages/types.ts +5 -0
  272. package/src/views/ResearchView/assistant/components/ToggleButtonGroup/stories/toggleButtonGroup.stories.tsx +22 -0
  273. package/src/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.styles.ts +22 -0
  274. package/src/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.tsx +34 -0
  275. package/src/views/ResearchView/assistant/stories/args.ts +36 -0
  276. package/src/views/ResearchView/assistant/stories/assistant.stories.tsx +39 -0
  277. package/src/views/ResearchView/query/constants.ts +5 -0
  278. package/src/views/ResearchView/query/fetch.ts +58 -0
  279. package/src/views/ResearchView/researchView.tsx +19 -0
  280. package/src/views/ResearchView/state/actions/setError/action.ts +22 -0
  281. package/src/views/ResearchView/state/actions/setError/dispatch.ts +14 -0
  282. package/src/views/ResearchView/state/actions/setError/types.ts +16 -0
  283. package/src/views/ResearchView/state/actions/setMessage/action.ts +26 -0
  284. package/src/views/ResearchView/state/actions/setMessage/dispatch.ts +14 -0
  285. package/src/views/ResearchView/state/actions/setMessage/types.ts +19 -0
  286. package/src/views/ResearchView/state/actions/setQuery/action.ts +22 -0
  287. package/src/views/ResearchView/state/actions/setQuery/dispatch.ts +14 -0
  288. package/src/views/ResearchView/state/actions/setQuery/types.ts +16 -0
  289. package/src/views/ResearchView/state/actions/setStatus/action.ts +19 -0
  290. package/src/views/ResearchView/state/actions/setStatus/dispatch.ts +14 -0
  291. package/src/views/ResearchView/state/actions/setStatus/types.ts +16 -0
  292. package/src/views/ResearchView/state/actions/types.ts +23 -0
  293. package/src/views/ResearchView/state/constants.ts +9 -0
  294. package/src/views/ResearchView/state/context.ts +11 -0
  295. package/src/views/ResearchView/state/guards/guards.ts +58 -0
  296. package/src/views/ResearchView/state/hooks/UseChatDispatch/hook.ts +46 -0
  297. package/src/views/ResearchView/state/hooks/UseChatDispatch/types.ts +11 -0
  298. package/src/views/ResearchView/state/hooks/UseChatReducer/hook.ts +15 -0
  299. package/src/views/ResearchView/state/hooks/UseChatState/hook.ts +14 -0
  300. package/src/views/ResearchView/state/initializer/initializer.ts +23 -0
  301. package/src/views/ResearchView/state/initializer/types.ts +3 -0
  302. package/src/views/ResearchView/state/provider.tsx +34 -0
  303. package/src/views/ResearchView/state/query/context.ts +9 -0
  304. package/src/views/ResearchView/state/query/hooks/UseQuery/hook.ts +11 -0
  305. package/src/views/ResearchView/state/query/hooks/UseSubmit/hook.ts +66 -0
  306. package/src/views/ResearchView/state/query/provider.tsx +27 -0
  307. package/src/views/ResearchView/state/query/types.ts +31 -0
  308. package/src/views/ResearchView/state/reducer.ts +34 -0
  309. package/src/views/ResearchView/state/types.ts +149 -0
  310. package/tests/research.assistantMessageUtils.test.ts +149 -0
  311. package/tests/research.chatState.test.ts +463 -0
  312. package/tests/research.fetchResponse.test.ts +164 -0
  313. package/tests/research.queryProvider.test.ts +321 -0
  314. package/tests/research.useKeyShortCuts.test.ts +254 -0
  315. package/tests/toggleButtonGroupProvider.test.tsx +125 -0
@@ -81,7 +81,11 @@ function buildTabLabel(
81
81
  annotation?: DataDictionaryAnnotation,
82
82
  ): ReactElement {
83
83
  return (
84
- <Tooltip description={annotation?.description} title={annotation?.label}>
84
+ <Tooltip
85
+ description={annotation?.description}
86
+ enterDelay={300}
87
+ title={annotation?.label}
88
+ >
85
89
  <span>{count ? `${label} (${count})` : label}</span>
86
90
  </Tooltip>
87
91
  );
@@ -0,0 +1,9 @@
1
+ import { createContext } from "react";
2
+ import { ToggleButtonGroupContextProps } from "./types";
3
+
4
+ export const ToggleButtonGroupContext = createContext<
5
+ ToggleButtonGroupContextProps<unknown>
6
+ >({
7
+ onChange: undefined,
8
+ value: null,
9
+ });
@@ -0,0 +1,16 @@
1
+ import { ToggleButtonGroupProps } from "@mui/material";
2
+ import { useContext } from "react";
3
+ import { ToggleButtonGroupContext } from "./context";
4
+ import { ToggleButtonGroupContextProps } from "./types";
5
+
6
+ /**
7
+ * Returns the toggle button group context.
8
+ * @returns toggle button group context.
9
+ */
10
+ export const useToggleButtonGroup = <
11
+ T extends ToggleButtonGroupProps["value"],
12
+ >(): ToggleButtonGroupContextProps<T> => {
13
+ return useContext(
14
+ ToggleButtonGroupContext,
15
+ ) as ToggleButtonGroupContextProps<T>;
16
+ };
@@ -0,0 +1,37 @@
1
+ import { ToggleButtonGroupProps } from "@mui/material";
2
+ import { JSX, MouseEvent, useCallback, useState } from "react";
3
+ import { ToggleButtonGroupContext } from "./context";
4
+ import { ToggleButtonGroupProviderProps } from "./types";
5
+
6
+ /**
7
+ * ToggleButtonGroup provider component.
8
+ * Manages toggle button group state for child components.
9
+ * @param props - Component props.
10
+ * @param props.children - Child elements to render.
11
+ * @param props.initialValue - Initial value for the toggle button group.
12
+ * @returns ToggleButtonGroup provider component.
13
+ */
14
+ export function ToggleButtonGroupProvider<
15
+ T extends ToggleButtonGroupProps["value"],
16
+ >({
17
+ children,
18
+ initialValue = null,
19
+ }: ToggleButtonGroupProviderProps<T>): JSX.Element {
20
+ const [value, setValue] = useState<T | null>(initialValue);
21
+
22
+ const onChange = useCallback(
23
+ (_: MouseEvent<HTMLElement>, value: T | null) => {
24
+ if (value === null) return;
25
+ setValue(value);
26
+ },
27
+ [],
28
+ );
29
+
30
+ return (
31
+ <ToggleButtonGroupContext.Provider value={{ onChange, value }}>
32
+ {typeof children === "function"
33
+ ? children({ onChange, value })
34
+ : children}
35
+ </ToggleButtonGroupContext.Provider>
36
+ );
37
+ }
@@ -0,0 +1,17 @@
1
+ import { ToggleButtonGroupProps } from "@mui/material";
2
+ import { ReactNode } from "react";
3
+
4
+ export type ToggleButtonGroupContextProps<
5
+ T extends ToggleButtonGroupProps["value"],
6
+ > = Pick<ToggleButtonGroupProps, "onChange"> & {
7
+ value: T | null;
8
+ };
9
+
10
+ export type ToggleButtonGroupProviderProps<
11
+ T extends ToggleButtonGroupProps["value"],
12
+ > = {
13
+ children:
14
+ | ReactNode
15
+ | ((props: ToggleButtonGroupContextProps<T>) => ReactNode);
16
+ initialValue?: T | null;
17
+ };
@@ -27,6 +27,7 @@ import { ProviderId } from "../providers/authentication/common/types";
27
27
  import { ExploreState } from "../providers/exploreState";
28
28
  import { FileManifestState } from "../providers/fileManifestState";
29
29
  import { SystemStatus, SystemStatusResponse } from "../providers/systemStatus";
30
+ import { AiConfig } from "../common/ai/config/types";
30
31
 
31
32
  /**
32
33
  * Interface to define the analytics configuration for a given site.
@@ -364,6 +365,7 @@ interface TrackingConfig {
364
365
  * Interface that will hold the whole configuration for a given site.
365
366
  */
366
367
  export interface SiteConfig {
368
+ ai?: AiConfig;
367
369
  analytics?: AnalyticsConfig;
368
370
  appTitle: string;
369
371
  authentication?: AuthenticationConfig;
@@ -0,0 +1,22 @@
1
+ import { FEATURE_FLAG } from "../../../common/ai/constants";
2
+ import { AiConfig } from "../../../common/ai/config/types";
3
+ import { useConfig } from "../../useConfig";
4
+ import { useFeatureFlag } from "../../useFeatureFlag/useFeatureFlag";
5
+
6
+ /**
7
+ * Returns AI route configuration when the AI feature is enabled.
8
+ * @returns AI routes, or undefined if AI is not configured or enabled.
9
+ */
10
+ export const useAiRoutes = (): Pick<AiConfig, "routes"> | undefined => {
11
+ const flagEnabled = useFeatureFlag(FEATURE_FLAG.CHAT);
12
+ const { config } = useConfig();
13
+ const { ai } = config;
14
+
15
+ if (!ai) return;
16
+
17
+ const { enabled, routes } = ai;
18
+
19
+ if (enabled || flagEnabled) {
20
+ return { routes };
21
+ }
22
+ };
@@ -0,0 +1,24 @@
1
+ import { DrawerProps } from "@mui/material";
2
+
3
+ type DrawerPropsOptions = {
4
+ ANCHOR: typeof ANCHOR;
5
+ VARIANT: typeof VARIANT;
6
+ };
7
+
8
+ const ANCHOR: Record<string, DrawerProps["anchor"]> = {
9
+ BOTTOM: "bottom",
10
+ LEFT: "left",
11
+ RIGHT: "right",
12
+ TOP: "top",
13
+ };
14
+
15
+ const VARIANT: Record<string, DrawerProps["variant"]> = {
16
+ PERMANENT: "permanent",
17
+ PERSISTENT: "persistent",
18
+ TEMPORARY: "temporary",
19
+ };
20
+
21
+ export const DRAWER_PROPS: DrawerPropsOptions = {
22
+ ANCHOR,
23
+ VARIANT,
24
+ };
@@ -0,0 +1,38 @@
1
+ import { InputBaseProps } from "@mui/material";
2
+
3
+ type InputBasePropsOptions = {
4
+ COLOR: typeof COLOR;
5
+ MARGIN: typeof MARGIN;
6
+ SIZE: typeof SIZE;
7
+ TYPE: typeof TYPE;
8
+ };
9
+
10
+ const COLOR: Record<string, InputBaseProps["color"]> = {
11
+ ERROR: "error",
12
+ INFO: "info",
13
+ PRIMARY: "primary",
14
+ SECONDARY: "secondary",
15
+ SUCCESS: "success",
16
+ WARNING: "warning",
17
+ };
18
+
19
+ const MARGIN: Record<string, InputBaseProps["margin"]> = {
20
+ DENSE: "dense",
21
+ NONE: "none",
22
+ };
23
+
24
+ const SIZE: Record<string, InputBaseProps["size"]> = {
25
+ MEDIUM: "medium",
26
+ SMALL: "small",
27
+ };
28
+
29
+ const TYPE: Record<string, InputBaseProps["type"]> = {
30
+ TEXT: "text",
31
+ };
32
+
33
+ export const INPUT_BASE_PROPS: InputBasePropsOptions = {
34
+ COLOR,
35
+ MARGIN,
36
+ SIZE,
37
+ TYPE,
38
+ };
@@ -0,0 +1,33 @@
1
+ import { StackProps } from "@mui/material";
2
+
3
+ type StackPropsOptions = {
4
+ ALIGN_ITEMS: typeof ALIGN_ITEMS;
5
+ DIRECTION: typeof DIRECTION;
6
+ FLEX_WRAP: typeof FLEX_WRAP;
7
+ };
8
+
9
+ const ALIGN_ITEMS: Record<string, StackProps["alignItems"]> = {
10
+ BASELINE: "baseline",
11
+ CENTER: "center",
12
+ FLEX_END: "flex-end",
13
+ FLEX_START: "flex-start",
14
+ STRETCH: "stretch",
15
+ } as const;
16
+
17
+ const DIRECTION: Record<string, StackProps["direction"]> = {
18
+ COLUMN: "column",
19
+ COLUMN_REVERSE: "column-reverse",
20
+ ROW: "row",
21
+ ROW_REVERSE: "row-reverse",
22
+ } as const;
23
+
24
+ const FLEX_WRAP: Record<string, StackProps["flexWrap"]> = {
25
+ WRAP: "wrap",
26
+ WRAP_REVERSE: "wrap-reverse",
27
+ } as const;
28
+
29
+ export const STACK_PROPS: StackPropsOptions = {
30
+ ALIGN_ITEMS,
31
+ DIRECTION,
32
+ FLEX_WRAP,
33
+ };
@@ -12,7 +12,10 @@ export const TEST_IDS = {
12
12
  FILTER_SORT_BUTTON: "filter-sort-button",
13
13
  FILTER_SORT_MENU: "filter-sort-menu",
14
14
  FILTER_TERM: "filter-term",
15
+ RESEARCH_FORM: "research-form",
16
+ RESEARCH_PANEL: "research-panel",
15
17
  SEARCH_ALL_FILTERS: "search-all-filters",
18
+ SEARCH_PANEL: "search-panel",
16
19
  SIDEBAR: "sidebar",
17
20
  SIDEBAR_DRAWER: "sidebar-drawer",
18
21
  TABLE_FIRST_CELL: "table-first-cell",
@@ -0,0 +1,25 @@
1
+ import styled from "@emotion/styled";
2
+ import { Box, ToggleButtonGroup } from "@mui/material";
3
+ import { bpDownMd } from "../../../../../../styles/common/mixins/breakpoints";
4
+ import { PALETTE } from "../../../../../../styles/common/constants/palette";
5
+
6
+ export const StyledBox = styled(Box)`
7
+ margin-bottom: -16px;
8
+ padding: 16px;
9
+
10
+ ${bpDownMd} {
11
+ margin-bottom: 0;
12
+ }
13
+ `;
14
+
15
+ export const StyledToggleButtonGroup = styled(ToggleButtonGroup)`
16
+ .MuiToggleButton-root {
17
+ gap: 4px;
18
+ padding: 6px 16px;
19
+ text-transform: none;
20
+
21
+ &.Mui-disabled {
22
+ color: ${PALETTE.INK_LIGHT};
23
+ }
24
+ }
25
+ `;
@@ -0,0 +1,35 @@
1
+ import { ToggleButton } from "@mui/material";
2
+ import { JSX } from "react";
3
+ import { StyledBox } from "./toggleButtonGroup.styles";
4
+ import Link from "next/link";
5
+ import { useAiRoutes } from "../../../../../../hooks/ai/useAiRoutes/hook";
6
+ import { StyledToggleButtonGroup } from "./toggleButtonGroup.styles";
7
+ import { Beta } from "../../../../../../components/common/Chip/components/Beta/beta";
8
+
9
+ /**
10
+ * ToggleButtonGroup component for navigating between ExploreView and ResearchView.
11
+ * @returns ToggleButtonGroup JSX element, or null if routes are not configured.
12
+ */
13
+ export const ToggleButtonGroup = (): JSX.Element | null => {
14
+ const { routes } = useAiRoutes() || {};
15
+
16
+ if (!routes) return null;
17
+
18
+ return (
19
+ <StyledBox>
20
+ <StyledToggleButtonGroup exclusive>
21
+ <ToggleButton component={Link} href={routes.research} value="research">
22
+ Research <Beta />
23
+ </ToggleButton>
24
+ <ToggleButton
25
+ component={Link}
26
+ href={routes.search}
27
+ selected
28
+ value="search"
29
+ >
30
+ Search
31
+ </ToggleButton>
32
+ </StyledToggleButtonGroup>
33
+ </StyledBox>
34
+ );
35
+ };
@@ -0,0 +1,19 @@
1
+ import styled from "@emotion/styled";
2
+ import { Stack } from "@mui/material";
3
+ import { bpDownMd } from "../../../../styles/common/mixins/breakpoints";
4
+
5
+ export const StyledStack = styled(Stack)`
6
+ gap: 8px;
7
+ margin: 16px 0;
8
+ padding: 0 16px;
9
+
10
+ ${bpDownMd} {
11
+ margin: 8px 0;
12
+ }
13
+ `;
14
+
15
+ export const StyledGrid = styled.div`
16
+ display: grid;
17
+ gap: 16px;
18
+ grid-template-columns: 1fr auto;
19
+ `;
@@ -16,7 +16,6 @@ import { SearchAllFilters } from "../../components/Filter/components/SearchAllFi
16
16
  import { SURFACE_TYPE } from "../../components/Filter/components/surfaces/types";
17
17
  import { Index as IndexView } from "../../components/Index/index";
18
18
  import { SidebarLabel } from "../../components/Layout/components/Sidebar/components/SidebarLabel/sidebarLabel";
19
- import { SidebarTools } from "../../components/Layout/components/Sidebar/components/SidebarTools/sidebarTools.styles";
20
19
  import { Sidebar } from "../../components/Layout/components/Sidebar/sidebar";
21
20
  import { CategoryGroup } from "../../config/entities";
22
21
  import { useStateSyncManager } from "../../hooks/stateSyncManager/hook";
@@ -32,6 +31,8 @@ import { SELECT_CATEGORY_KEY } from "../../providers/exploreState/constants";
32
31
  import { TEST_IDS } from "../../tests/testIds";
33
32
  import { useUpdateFilterSort } from "./hooks/UseUpdateFilterSort/hook";
34
33
  import { buildStateSyncManagerContext } from "./utils";
34
+ import { StyledGrid, StyledStack } from "./entityList/filters/filters.styles";
35
+ import { ToggleButtonGroup } from "./entityList/filters/components/ToggleButtonGroup/toggleButtonGroup";
35
36
 
36
37
  export interface ExploreViewProps extends AzulEntitiesStaticResponse {
37
38
  className?: string;
@@ -137,16 +138,19 @@ export const ExploreView = (props: ExploreViewProps): JSX.Element => {
137
138
  <DrawerProvider>
138
139
  {categoryViews && !!categoryViews.length && (
139
140
  <Sidebar>
140
- <SidebarTools data-testid={TEST_IDS.FILTER_CONTROLS}>
141
- <SidebarLabel label={"Filters"} />
142
- <Stack direction="row" gap={4}>
143
- <ClearAllFilters />
144
- <FilterSort
145
- enabled={filterSortEnabled}
146
- filterSort={filterSort}
147
- onFilterSortChange={onFilterSortChange}
148
- />
149
- </Stack>
141
+ <ToggleButtonGroup />
142
+ <StyledStack>
143
+ <StyledGrid data-testid={TEST_IDS.FILTER_CONTROLS}>
144
+ <SidebarLabel label={"Filters"} />
145
+ <Stack direction="row" gap={4}>
146
+ <ClearAllFilters />
147
+ <FilterSort
148
+ enabled={filterSortEnabled}
149
+ filterSort={filterSort}
150
+ onFilterSortChange={onFilterSortChange}
151
+ />
152
+ </Stack>
153
+ </StyledGrid>
150
154
  <SearchAllFilters
151
155
  categoryViews={categoryViews}
152
156
  onFilter={onFilterChange.bind(null, true)}
@@ -154,7 +158,7 @@ export const ExploreView = (props: ExploreViewProps): JSX.Element => {
154
158
  mdDown ? SURFACE_TYPE.POPPER_DRAWER : SURFACE_TYPE.POPPER_MENU
155
159
  }
156
160
  />
157
- </SidebarTools>
161
+ </StyledStack>
158
162
  <Filters
159
163
  categoryFilters={categoryFilters}
160
164
  onFilter={onFilterChange.bind(null, false)}
@@ -0,0 +1,28 @@
1
+ import { JSX } from "react";
2
+ import { useChatState } from "../state/hooks/UseChatState/hook";
3
+ import { Form } from "./components/Form/form";
4
+ import { Input } from "./components/Input/input";
5
+ import { getPlaceholder } from "./components/Input/utils";
6
+ import { Messages } from "./components/Messages/messages";
7
+ import { Drawer } from "./components/Drawer/drawer";
8
+ import { ToggleButtonGroup } from "./components/ToggleButtonGroup/toggleButtonGroup";
9
+
10
+ /**
11
+ * Renders the research assistant drawer.
12
+ * @returns The assistant drawer.
13
+ */
14
+ export const Assistant = (): JSX.Element => {
15
+ const { state } = useChatState();
16
+ return (
17
+ <Drawer>
18
+ <ToggleButtonGroup />
19
+ <Form status={state.status}>
20
+ <Messages state={state} />
21
+ <Input
22
+ disabled={state.status.loading}
23
+ placeholder={getPlaceholder(state)}
24
+ />
25
+ </Form>
26
+ </Drawer>
27
+ );
28
+ };
@@ -0,0 +1,24 @@
1
+ import styled from "@emotion/styled";
2
+ import { Drawer } from "@mui/material";
3
+ import { PALETTE } from "../../../../../styles/common/constants/palette";
4
+ import { ComponentProps } from "react";
5
+ import { LayoutSpacing } from "../../../../../hooks/UseLayoutSpacing/types";
6
+
7
+ export const StyledDrawer = styled(Drawer, {
8
+ shouldForwardProp(prop) {
9
+ return prop !== "bottom" && prop !== "top";
10
+ },
11
+ })<ComponentProps<typeof Drawer> & LayoutSpacing>`
12
+ height: 100%;
13
+ max-height: 100dvh;
14
+ width: 412px;
15
+ z-index: 0;
16
+
17
+ > .MuiPaper-root {
18
+ background-color: ${PALETTE.COMMON_WHITE};
19
+ border-right: 1px solid ${PALETTE.SMOKE_MAIN};
20
+ padding-top: ${({ top }) => top}px;
21
+ position: relative;
22
+ width: inherit;
23
+ }
24
+ `;
@@ -0,0 +1,26 @@
1
+ import { JSX } from "react";
2
+ import { TEST_IDS } from "../../../../../tests/testIds";
3
+ import { StyledDrawer } from "./drawer.styles";
4
+ import { DrawerProps } from "./types";
5
+ import { useLayoutSpacing } from "../../../../../hooks/UseLayoutSpacing/hook";
6
+ import { DRAWER_PROPS } from "../../../../../styles/common/mui/drawer";
7
+
8
+ /**
9
+ * Renders the drawer component for the research assistant.
10
+ * @param props - Component props.
11
+ * @param props.children - Children.
12
+ * @returns The drawer component.
13
+ */
14
+ export const Drawer = ({ children }: DrawerProps): JSX.Element => {
15
+ const { spacing } = useLayoutSpacing();
16
+ return (
17
+ <StyledDrawer
18
+ data-testid={TEST_IDS.RESEARCH_PANEL}
19
+ open
20
+ variant={DRAWER_PROPS.VARIANT.PERSISTENT}
21
+ {...spacing}
22
+ >
23
+ {children}
24
+ </StyledDrawer>
25
+ );
26
+ };
@@ -0,0 +1,5 @@
1
+ import { ReactNode } from "react";
2
+
3
+ export interface DrawerProps {
4
+ children: ReactNode;
5
+ }
@@ -0,0 +1,3 @@
1
+ export const FIELD_NAME = {
2
+ AI_PROMPT: "ai-prompt",
3
+ };
@@ -0,0 +1,8 @@
1
+ import styled from "@emotion/styled";
2
+
3
+ export const StyledForm = styled.form`
4
+ display: flex;
5
+ flex-direction: column;
6
+ height: 100%;
7
+ min-height: 0;
8
+ `;
@@ -0,0 +1,40 @@
1
+ import { JSX } from "react";
2
+ import { TEST_IDS } from "../../../../../tests/testIds";
3
+ import { useQuery } from "../../../state/query/hooks/UseQuery/hook";
4
+ import { FIELD_NAME } from "./constants";
5
+ import { StyledForm } from "./form.styles";
6
+ import { FormProps } from "./types";
7
+ import { getPayload } from "./utils";
8
+
9
+ /**
10
+ * Renders the research form.
11
+ * @param props - Component props.
12
+ * @param props.children - Form children.
13
+ * @param props.className - Class name for styling.
14
+ * @param props.status - Form status.
15
+ * @returns The research form container element.
16
+ */
17
+ export const Form = ({
18
+ children,
19
+ className,
20
+ status,
21
+ }: FormProps): JSX.Element => {
22
+ const { onSubmit } = useQuery();
23
+ return (
24
+ <StyledForm
25
+ className={className}
26
+ data-testid={TEST_IDS.RESEARCH_FORM}
27
+ onSubmit={async (e) => {
28
+ await onSubmit(e, getPayload(e), {
29
+ onSettled: (form) => {
30
+ const input = form.elements.namedItem(FIELD_NAME.AI_PROMPT);
31
+ if (input instanceof HTMLElement) input.focus();
32
+ },
33
+ status,
34
+ });
35
+ }}
36
+ >
37
+ {children}
38
+ </StyledForm>
39
+ );
40
+ };
@@ -0,0 +1,9 @@
1
+ import {
2
+ BaseComponentProps,
3
+ ChildrenProps,
4
+ } from "../../../../../components/types";
5
+ import { ChatState } from "../../../state/types";
6
+
7
+ export type FormProps = BaseComponentProps &
8
+ ChildrenProps &
9
+ Pick<ChatState, "status">;
@@ -0,0 +1,51 @@
1
+ import { FormEvent } from "react";
2
+ import { FIELD_NAME } from "./constants";
3
+ import { OnSubmitPayload } from "../../../state/query/types";
4
+
5
+ /**
6
+ * Extracts and trims form values from a form element.
7
+ * @param form - Form element.
8
+ * @returns An object mapping form field names to their trimmed string values.
9
+ */
10
+ export const getFormValues = (
11
+ form: HTMLFormElement,
12
+ ): Record<string, string> => {
13
+ const formData = new FormData(form);
14
+
15
+ const values: Record<string, string> = {};
16
+ formData.forEach((value, key) => {
17
+ values[key] = value.toString().trim();
18
+ });
19
+
20
+ return values;
21
+ };
22
+
23
+ /**
24
+ * Returns the payload for the query form submission.
25
+ * If the submitter has a data-query attribute (e.g. a suggestion chip), uses that as the query.
26
+ * Otherwise, falls back to the form input value.
27
+ * @param e - Form event.
28
+ * @returns The payload object containing the query value.
29
+ */
30
+ export const getPayload = (e: FormEvent<HTMLFormElement>): OnSubmitPayload => {
31
+ // Check for a query from the submitter's data-query attribute first
32
+ const query = getSubmitterQuery(e);
33
+
34
+ // The onSubmit handler will ignore empty queries which acts as a safeguard against empty data-query values.
35
+ if (query !== undefined) return { query };
36
+
37
+ // If no submitter query, fall back to form values
38
+ const formValues = getFormValues(e.currentTarget);
39
+ return { query: formValues[FIELD_NAME.AI_PROMPT] || "" };
40
+ };
41
+
42
+ /**
43
+ * Returns the query from the form submitter's data-query attribute, if present.
44
+ * @param e - Form event.
45
+ * @returns The query string, or undefined if the submitter has no data-query.
46
+ */
47
+ function getSubmitterQuery(e: FormEvent<HTMLFormElement>): string | undefined {
48
+ const submitter = (e.nativeEvent as SubmitEvent).submitter;
49
+ // We should expect a defined value here if the submitter is a data-query element, but we trim it just in case.
50
+ return submitter?.dataset.query?.trim();
51
+ }
@@ -0,0 +1,16 @@
1
+ import { InputBaseProps } from "@mui/material";
2
+ import { INPUT_BASE_PROPS as MUI_INPUT_BASE_PROPS } from "../../../../../styles/common/mui/inputBase";
3
+ import { FIELD_NAME } from "../Form/constants";
4
+
5
+ export const INPUT_BASE_PROPS: InputBaseProps = {
6
+ autoFocus: true,
7
+ color: MUI_INPUT_BASE_PROPS.COLOR.PRIMARY,
8
+ fullWidth: true,
9
+ inputProps: { autoComplete: "off", spellCheck: false },
10
+ margin: MUI_INPUT_BASE_PROPS.MARGIN.DENSE,
11
+ maxRows: 4,
12
+ minRows: 1,
13
+ multiline: true,
14
+ name: FIELD_NAME.AI_PROMPT,
15
+ placeholder: "Ask anything",
16
+ };
@@ -0,0 +1,7 @@
1
+ export const KEY = {
2
+ ARROW_DOWN: "ArrowDown",
3
+ ARROW_UP: "ArrowUp",
4
+ ENTER: "Enter",
5
+ ESCAPE: "Escape",
6
+ TAB: "Tab",
7
+ } as const;
@@ -0,0 +1,45 @@
1
+ import { KeyboardEvent, useCallback, useEffect, useRef } from "react";
2
+ import { useChatState } from "../../../../../state/hooks/UseChatState/hook";
3
+ import { KEY } from "./constants";
4
+ import { UseKeyShortCutsProps } from "./types";
5
+ import {
6
+ getHistory,
7
+ handleArrowKey,
8
+ handleEnterKey,
9
+ handleEscapeKey,
10
+ handleTabKey,
11
+ } from "./utils";
12
+
13
+ /**
14
+ * Provides a keydown handler that implements keyboard shortcuts for the assistant input.
15
+ * @returns An object containing the onKeyDown handler.
16
+ */
17
+ export const useKeyShortCuts = (): UseKeyShortCutsProps => {
18
+ const { state } = useChatState();
19
+ const { messages } = state;
20
+
21
+ const history = getHistory(messages);
22
+
23
+ const draftRef = useRef<string>("");
24
+ const historyIndexRef = useRef<number>(-1);
25
+
26
+ useEffect(() => {
27
+ // Resets history navigation when messages change.
28
+ draftRef.current = "";
29
+ historyIndexRef.current = -1;
30
+ }, [messages]);
31
+
32
+ const onKeyDown = useCallback(
33
+ (e: KeyboardEvent<HTMLInputElement>) => {
34
+ const refs = { draftRef, historyIndexRef };
35
+ if (e.key === KEY.ENTER) return handleEnterKey(e);
36
+ if (e.key === KEY.ESCAPE) return handleEscapeKey(e, refs);
37
+ if (e.key === KEY.ARROW_UP || e.key === KEY.ARROW_DOWN)
38
+ return handleArrowKey(e, history, refs);
39
+ if (e.key === KEY.TAB) return handleTabKey(e);
40
+ },
41
+ [history],
42
+ );
43
+
44
+ return { onKeyDown };
45
+ };