@databiosphere/findable-ui 49.1.0 → 49.3.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 (49) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +21 -0
  3. package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.d.ts +2 -3
  4. package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.js +3 -4
  5. package/lib/views/ResearchView/assistant/assistant.js +3 -5
  6. package/lib/views/ResearchView/assistant/components/Form/form.d.ts +1 -2
  7. package/lib/views/ResearchView/assistant/components/Form/form.js +5 -18
  8. package/lib/views/ResearchView/assistant/components/Form/types.d.ts +1 -2
  9. package/lib/views/ResearchView/assistant/components/Form/utils.d.ts +1 -1
  10. package/lib/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.d.ts +2 -1
  11. package/lib/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.js +5 -2
  12. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.d.ts +2 -3
  13. package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.js +3 -4
  14. package/lib/views/ResearchView/assistant/stories/assistant.stories.js +1 -1
  15. package/lib/views/ResearchView/state/provider.d.ts +4 -1
  16. package/lib/views/ResearchView/state/provider.js +5 -2
  17. package/lib/views/ResearchView/state/query/context.d.ts +5 -0
  18. package/lib/views/ResearchView/state/query/context.js +7 -0
  19. package/lib/views/ResearchView/state/query/hooks/UseQuery/hook.d.ts +6 -0
  20. package/lib/views/ResearchView/state/query/hooks/UseQuery/hook.js +9 -0
  21. package/lib/views/ResearchView/state/query/hooks/UseSubmit/hook.d.ts +7 -0
  22. package/lib/views/ResearchView/state/query/hooks/UseSubmit/hook.js +46 -0
  23. package/lib/views/ResearchView/state/query/provider.d.ts +13 -0
  24. package/lib/views/ResearchView/state/query/provider.js +15 -0
  25. package/lib/views/ResearchView/{query → state/query}/types.d.ts +5 -12
  26. package/package.json +1 -1
  27. package/src/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.tsx +10 -6
  28. package/src/views/ResearchView/assistant/assistant.tsx +3 -5
  29. package/src/views/ResearchView/assistant/components/Form/form.tsx +4 -19
  30. package/src/views/ResearchView/assistant/components/Form/types.ts +0 -2
  31. package/src/views/ResearchView/assistant/components/Form/utils.ts +1 -1
  32. package/src/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.ts +5 -2
  33. package/src/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.tsx +10 -6
  34. package/src/views/ResearchView/assistant/stories/assistant.stories.tsx +1 -1
  35. package/src/views/ResearchView/state/provider.tsx +8 -1
  36. package/src/views/ResearchView/state/query/context.ts +9 -0
  37. package/src/views/ResearchView/state/query/hooks/UseQuery/hook.ts +11 -0
  38. package/src/views/ResearchView/state/query/hooks/UseSubmit/hook.ts +66 -0
  39. package/src/views/ResearchView/state/query/provider.tsx +27 -0
  40. package/src/views/ResearchView/{query → state/query}/types.ts +9 -15
  41. package/tests/research.queryProvider.test.ts +321 -0
  42. package/lib/views/ResearchView/adapter/useAdapter.d.ts +0 -6
  43. package/lib/views/ResearchView/adapter/useAdapter.js +0 -15
  44. package/lib/views/ResearchView/query/useQuery.d.ts +0 -7
  45. package/lib/views/ResearchView/query/useQuery.js +0 -44
  46. package/src/views/ResearchView/adapter/useAdapter.ts +0 -19
  47. package/src/views/ResearchView/query/useQuery.ts +0 -60
  48. package/tests/research.useQuery.test.ts +0 -165
  49. /package/lib/views/ResearchView/{query → state/query}/types.js +0 -0
@@ -1,60 +0,0 @@
1
- import { FormEvent, useCallback, useEffect, useRef } from "react";
2
- import { OnSubmitOptions, OnSubmitPayload, UseQuery } from "./types";
3
- import { fetchResponse } from "./fetch";
4
-
5
- /**
6
- * Custom hook for managing the actions of a chat query form.
7
- * @param url - The URL to send the query to.
8
- * @returns An object containing the actions of the query.
9
- */
10
- export const useQuery = (url: string): UseQuery => {
11
- const abortRef = useRef<AbortController>(null);
12
-
13
- const onSubmit = useCallback(
14
- async (
15
- e: FormEvent<HTMLFormElement>,
16
- payload: OnSubmitPayload,
17
- options?: OnSubmitOptions,
18
- ) => {
19
- e.preventDefault();
20
-
21
- if (options?.status?.loading) return;
22
-
23
- const form = e.currentTarget;
24
- const { query } = payload;
25
-
26
- if (!query) return;
27
-
28
- // Call onMutate callback
29
- options?.onMutate?.(form, query);
30
-
31
- // Abort any in-flight request
32
- abortRef.current?.abort();
33
- const controller = new AbortController();
34
- abortRef.current = controller;
35
-
36
- await fetchResponse(url, query, {
37
- controller,
38
- onError: (error) => {
39
- options?.onError?.(error);
40
- },
41
- onSettled: () => {
42
- options?.onSettled?.(form);
43
- },
44
- onSuccess: (data) => {
45
- options?.onSuccess?.(data);
46
- },
47
- });
48
- },
49
- [url],
50
- );
51
-
52
- // Abort any in-flight request on unmount.
53
- useEffect(() => {
54
- return (): void => {
55
- abortRef.current?.abort();
56
- };
57
- }, []);
58
-
59
- return { actions: { onSubmit } };
60
- };
@@ -1,165 +0,0 @@
1
- import { jest } from "@jest/globals";
2
- import { act, renderHook } from "@testing-library/react";
3
- import { FormEvent } from "react";
4
-
5
- /**
6
- * Fetch callbacks passed to fetchResponse.
7
- */
8
- interface FetchCallbacks {
9
- controller: AbortController;
10
- onError: (error: Error) => void;
11
- onSettled: () => void;
12
- onSuccess: (data: unknown) => void;
13
- }
14
-
15
- // Mock fetchResponse
16
- const mockFetchResponse = jest.fn();
17
-
18
- jest.unstable_mockModule("../src/views/ResearchView/query/fetch", () => ({
19
- fetchResponse: mockFetchResponse,
20
- }));
21
-
22
- const { useQuery } = await import("../src/views/ResearchView/query/useQuery");
23
-
24
- /**
25
- * Creates a mock form event for testing.
26
- * @returns Mock FormEvent.
27
- */
28
- function createMockFormEvent(): FormEvent<HTMLFormElement> {
29
- const mockForm = document.createElement("form");
30
-
31
- // Mock reset
32
- mockForm.reset = jest.fn();
33
-
34
- return {
35
- currentTarget: mockForm,
36
- preventDefault: jest.fn(),
37
- } as unknown as FormEvent<HTMLFormElement>;
38
- }
39
-
40
- describe("useQuery", () => {
41
- beforeEach(() => {
42
- mockFetchResponse.mockReset();
43
- mockFetchResponse.mockImplementation(
44
- async (_url: unknown, _query: unknown, callbacks: unknown) => {
45
- (callbacks as FetchCallbacks).onSettled();
46
- },
47
- );
48
- });
49
-
50
- describe("initial state", () => {
51
- it("should return onSubmit function", () => {
52
- const { result } = renderHook(() => useQuery("https://api.example.com"));
53
-
54
- expect(typeof result.current.actions.onSubmit).toBe("function");
55
- });
56
- });
57
-
58
- describe("submit guards", () => {
59
- it("should not submit if query is empty", async () => {
60
- const { result } = renderHook(() => useQuery("https://api.example.com"));
61
- const event = createMockFormEvent();
62
-
63
- await act(async () => {
64
- await result.current.actions.onSubmit(event, { query: "" });
65
- });
66
-
67
- expect(mockFetchResponse).not.toHaveBeenCalled();
68
- });
69
-
70
- it("should submit if query is provided", async () => {
71
- const { result } = renderHook(() => useQuery("https://api.example.com"));
72
- const event = createMockFormEvent();
73
-
74
- await act(async () => {
75
- await result.current.actions.onSubmit(event, { query: "valid query" });
76
- });
77
-
78
- expect(mockFetchResponse).toHaveBeenCalled();
79
- });
80
- });
81
-
82
- describe("submit behavior", () => {
83
- it("should call preventDefault on form event", async () => {
84
- const { result } = renderHook(() => useQuery("https://api.example.com"));
85
- const event = createMockFormEvent();
86
-
87
- await act(async () => {
88
- await result.current.actions.onSubmit(event, {
89
- query: "diabetes studies",
90
- });
91
- });
92
-
93
- expect(event.preventDefault).toHaveBeenCalled();
94
- });
95
-
96
- it("should call fetchResponse with correct arguments", async () => {
97
- const { result } = renderHook(() => useQuery("https://api.example.com"));
98
- const event = createMockFormEvent();
99
-
100
- await act(async () => {
101
- await result.current.actions.onSubmit(event, {
102
- query: "diabetes studies",
103
- });
104
- });
105
-
106
- expect(mockFetchResponse).toHaveBeenCalledWith(
107
- "https://api.example.com",
108
- "diabetes studies",
109
- expect.objectContaining({
110
- controller: expect.any(AbortController),
111
- onError: expect.any(Function),
112
- onSettled: expect.any(Function),
113
- onSuccess: expect.any(Function),
114
- }),
115
- );
116
- });
117
-
118
- it("should pass url to fetchResponse", async () => {
119
- const testUrl = "https://custom-api.example.com/search";
120
- const { result } = renderHook(() => useQuery(testUrl));
121
- const event = createMockFormEvent();
122
-
123
- await act(async () => {
124
- await result.current.actions.onSubmit(event, {
125
- query: "cancer studies",
126
- });
127
- });
128
-
129
- expect(mockFetchResponse).toHaveBeenCalledWith(
130
- testUrl,
131
- expect.any(String),
132
- expect.any(Object),
133
- );
134
- });
135
- });
136
-
137
- describe("abort handling", () => {
138
- it("should create new AbortController for each submit", async () => {
139
- const controllers: AbortController[] = [];
140
- mockFetchResponse.mockImplementation(
141
- async (_url: unknown, _query: unknown, callbacks: unknown) => {
142
- controllers.push((callbacks as FetchCallbacks).controller);
143
- (callbacks as FetchCallbacks).onSettled();
144
- },
145
- );
146
-
147
- const { result } = renderHook(() => useQuery("https://api.example.com"));
148
-
149
- await act(async () => {
150
- await result.current.actions.onSubmit(createMockFormEvent(), {
151
- query: "query 1",
152
- });
153
- });
154
-
155
- await act(async () => {
156
- await result.current.actions.onSubmit(createMockFormEvent(), {
157
- query: "query 2",
158
- });
159
- });
160
-
161
- expect(controllers).toHaveLength(2);
162
- expect(controllers[0]).not.toBe(controllers[1]);
163
- });
164
- });
165
- });