@gooddata/sdk-ui-ext 11.32.0-alpha.1 → 11.32.0-alpha.3

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 (68) hide show
  1. package/NOTICE +6 -6
  2. package/esm/index.d.ts +4 -1
  3. package/esm/index.d.ts.map +1 -1
  4. package/esm/index.js +2 -0
  5. package/esm/index.js.map +1 -1
  6. package/esm/insightPicker/InsightPicker.d.ts +18 -0
  7. package/esm/insightPicker/InsightPicker.d.ts.map +1 -0
  8. package/esm/insightPicker/InsightPicker.js +29 -0
  9. package/esm/insightPicker/InsightPicker.js.map +1 -0
  10. package/esm/insightPicker/InsightPickerCore.d.ts +3 -0
  11. package/esm/insightPicker/InsightPickerCore.d.ts.map +1 -0
  12. package/esm/insightPicker/InsightPickerCore.js +117 -0
  13. package/esm/insightPicker/InsightPickerCore.js.map +1 -0
  14. package/esm/insightPicker/InsightPickerFilterBar.d.ts +21 -0
  15. package/esm/insightPicker/InsightPickerFilterBar.d.ts.map +1 -0
  16. package/esm/insightPicker/InsightPickerFilterBar.js +46 -0
  17. package/esm/insightPicker/InsightPickerFilterBar.js.map +1 -0
  18. package/esm/insightPicker/InsightPickerMenu.d.ts +10 -0
  19. package/esm/insightPicker/InsightPickerMenu.d.ts.map +1 -0
  20. package/esm/insightPicker/InsightPickerMenu.js +22 -0
  21. package/esm/insightPicker/InsightPickerMenu.js.map +1 -0
  22. package/esm/insightPicker/InsightPickerRow.d.ts +17 -0
  23. package/esm/insightPicker/InsightPickerRow.d.ts.map +1 -0
  24. package/esm/insightPicker/InsightPickerRow.js +19 -0
  25. package/esm/insightPicker/InsightPickerRow.js.map +1 -0
  26. package/esm/insightPicker/InsightPickerSortDropdown.d.ts +9 -0
  27. package/esm/insightPicker/InsightPickerSortDropdown.d.ts.map +1 -0
  28. package/esm/insightPicker/InsightPickerSortDropdown.js +29 -0
  29. package/esm/insightPicker/InsightPickerSortDropdown.js.map +1 -0
  30. package/esm/insightPicker/messages.d.ts +60 -0
  31. package/esm/insightPicker/messages.d.ts.map +1 -0
  32. package/esm/insightPicker/messages.js +62 -0
  33. package/esm/insightPicker/messages.js.map +1 -0
  34. package/esm/insightPicker/types.d.ts +107 -0
  35. package/esm/insightPicker/types.d.ts.map +1 -0
  36. package/esm/insightPicker/types.js +3 -0
  37. package/esm/insightPicker/types.js.map +1 -0
  38. package/esm/insightPicker/useInsightPickerFilters.d.ts +17 -0
  39. package/esm/insightPicker/useInsightPickerFilters.d.ts.map +1 -0
  40. package/esm/insightPicker/useInsightPickerFilters.js +55 -0
  41. package/esm/insightPicker/useInsightPickerFilters.js.map +1 -0
  42. package/esm/insightPicker/useInsightPickerHybridSearch.d.ts +25 -0
  43. package/esm/insightPicker/useInsightPickerHybridSearch.d.ts.map +1 -0
  44. package/esm/insightPicker/useInsightPickerHybridSearch.js +66 -0
  45. package/esm/insightPicker/useInsightPickerHybridSearch.js.map +1 -0
  46. package/esm/insightPicker/useInsightPickerState.d.ts +21 -0
  47. package/esm/insightPicker/useInsightPickerState.d.ts.map +1 -0
  48. package/esm/insightPicker/useInsightPickerState.js +49 -0
  49. package/esm/insightPicker/useInsightPickerState.js.map +1 -0
  50. package/esm/internal/components/insightList/useInsightPagedList.d.ts +33 -1
  51. package/esm/internal/components/insightList/useInsightPagedList.d.ts.map +1 -1
  52. package/esm/internal/components/insightList/useInsightPagedList.js +37 -9
  53. package/esm/internal/components/insightList/useInsightPagedList.js.map +1 -1
  54. package/esm/internal/index.d.ts +1 -1
  55. package/esm/internal/index.d.ts.map +1 -1
  56. package/esm/internal/index.js.map +1 -1
  57. package/esm/internal/translations/en-US.localization-bundle.d.ts +76 -0
  58. package/esm/internal/translations/en-US.localization-bundle.d.ts.map +1 -1
  59. package/esm/internal/translations/en-US.localization-bundle.js +76 -0
  60. package/esm/internal/translations/en-US.localization-bundle.js.map +1 -1
  61. package/esm/sdk-ui-ext.d.ts +183 -1
  62. package/package.json +21 -20
  63. package/styles/css/main.css +160 -0
  64. package/styles/css/main.css.map +1 -1
  65. package/styles/internal/css/insightPicker.css +161 -0
  66. package/styles/internal/css/insightPicker.css.map +1 -0
  67. package/styles/internal/scss/insightPicker.scss +189 -0
  68. package/styles/scss/main.scss +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/insightPicker/messages.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DnB,CAAC"}
@@ -0,0 +1,62 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { defineMessages } from "react-intl";
3
+ export const messages = defineMessages({
4
+ searchPlaceholder: {
5
+ id: "insightPicker.searchPlaceholder",
6
+ },
7
+ tabAll: {
8
+ id: "insightPicker.tabs.all",
9
+ },
10
+ tabMy: {
11
+ id: "insightPicker.tabs.my",
12
+ },
13
+ noInsightsFound: {
14
+ id: "insightPicker.noInsightsFound",
15
+ },
16
+ noInsights: {
17
+ id: "insightPicker.noInsights",
18
+ },
19
+ sortByHeader: {
20
+ id: "insightPicker.sortBy.header",
21
+ },
22
+ sortByLastModified: {
23
+ id: "insightPicker.sortBy.lastModified",
24
+ },
25
+ sortByName: {
26
+ id: "insightPicker.sortBy.name",
27
+ },
28
+ filters: {
29
+ id: "insightPicker.filters",
30
+ },
31
+ filterCreatedBy: {
32
+ id: "insightPicker.filter.createdBy",
33
+ },
34
+ filterCreatedByMe: {
35
+ id: "insightPicker.filter.createdByMe",
36
+ },
37
+ filterAll: {
38
+ id: "insightPicker.filter.all",
39
+ },
40
+ filterApply: {
41
+ id: "insightPicker.filter.apply",
42
+ },
43
+ filterCancel: {
44
+ id: "insightPicker.filter.cancel",
45
+ },
46
+ filterTag: {
47
+ id: "insightPicker.filter.tag",
48
+ },
49
+ sortDirectionAscending: {
50
+ id: "insightPicker.sortDirection.ascending",
51
+ },
52
+ sortDirectionDescending: {
53
+ id: "insightPicker.sortDirection.descending",
54
+ },
55
+ menuActions: {
56
+ id: "insightPicker.menu.actions",
57
+ },
58
+ resetFilters: {
59
+ id: "insightPicker.resetFilters",
60
+ },
61
+ });
62
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/insightPicker/messages.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC;IACnC,iBAAiB,EAAE;QACf,EAAE,EAAE,iCAAiC;KACxC;IACD,MAAM,EAAE;QACJ,EAAE,EAAE,wBAAwB;KAC/B;IACD,KAAK,EAAE;QACH,EAAE,EAAE,uBAAuB;KAC9B;IACD,eAAe,EAAE;QACb,EAAE,EAAE,+BAA+B;KACtC;IACD,UAAU,EAAE;QACR,EAAE,EAAE,0BAA0B;KACjC;IACD,YAAY,EAAE;QACV,EAAE,EAAE,6BAA6B;KACpC;IACD,kBAAkB,EAAE;QAChB,EAAE,EAAE,mCAAmC;KAC1C;IACD,UAAU,EAAE;QACR,EAAE,EAAE,2BAA2B;KAClC;IACD,OAAO,EAAE;QACL,EAAE,EAAE,uBAAuB;KAC9B;IACD,eAAe,EAAE;QACb,EAAE,EAAE,gCAAgC;KACvC;IACD,iBAAiB,EAAE;QACf,EAAE,EAAE,kCAAkC;KACzC;IACD,SAAS,EAAE;QACP,EAAE,EAAE,0BAA0B;KACjC;IACD,WAAW,EAAE;QACT,EAAE,EAAE,4BAA4B;KACnC;IACD,YAAY,EAAE;QACV,EAAE,EAAE,6BAA6B;KACpC;IACD,SAAS,EAAE;QACP,EAAE,EAAE,0BAA0B;KACjC;IACD,sBAAsB,EAAE;QACpB,EAAE,EAAE,uCAAuC;KAC9C;IACD,uBAAuB,EAAE;QACrB,EAAE,EAAE,wCAAwC;KAC/C;IACD,WAAW,EAAE;QACT,EAAE,EAAE,4BAA4B;KACnC;IACD,YAAY,EAAE;QACV,EAAE,EAAE,4BAA4B;KACnC;CACJ,CAAC,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { type ReactElement, type ReactNode } from "react";
2
+ import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
3
+ import { type IInsight, type ObjRef } from "@gooddata/sdk-model";
4
+ import { type ILocale } from "@gooddata/sdk-ui";
5
+ /**
6
+ * Sort field for the insight picker.
7
+ * @internal
8
+ */
9
+ export type InsightPickerSortBy = "lastModified" | "name";
10
+ /**
11
+ * Sort direction for the insight picker.
12
+ * @internal
13
+ */
14
+ export type InsightPickerSortDirection = "asc" | "desc";
15
+ /**
16
+ * Represents a single insight item in the picker.
17
+ * @internal
18
+ */
19
+ export interface IInsightPickerItem {
20
+ ref: ObjRef;
21
+ title: string;
22
+ description?: string;
23
+ identifier: string;
24
+ uri?: string;
25
+ isLocked: boolean;
26
+ created?: string;
27
+ updated?: string;
28
+ visualizationUrl: string;
29
+ }
30
+ /**
31
+ * Menu action for the insight picker's three-dots menu.
32
+ * @internal
33
+ */
34
+ export interface IInsightPickerMenuAction {
35
+ id: string;
36
+ title: string;
37
+ onClick: (item: IInsightPickerItem) => void;
38
+ isDestructive?: boolean;
39
+ hasSeparator?: boolean;
40
+ }
41
+ /**
42
+ * Props for a custom menu renderer.
43
+ * @internal
44
+ */
45
+ export interface IInsightPickerMenuProps {
46
+ item: IInsightPickerItem;
47
+ closeMenu: () => void;
48
+ }
49
+ /**
50
+ * Props passed to a custom renderItem function.
51
+ * @internal
52
+ */
53
+ export interface IInsightPickerRenderItemProps {
54
+ item: IInsightPickerItem;
55
+ type: string;
56
+ width: number;
57
+ isSelected: boolean;
58
+ sourceInsight?: IInsight;
59
+ }
60
+ /**
61
+ * Props for the InsightPicker component.
62
+ *
63
+ * The picker is fully controlled — all state (search, sort, filters) must be
64
+ * managed by the consumer and passed as props. This ensures state persists
65
+ * across open/close cycles.
66
+ *
67
+ * @internal
68
+ */
69
+ export interface IInsightPickerProps {
70
+ backend?: IAnalyticalBackend;
71
+ workspace?: string;
72
+ locale?: ILocale;
73
+ /** Include only insights with these tags (URL-scoped). */
74
+ includeTags?: string[];
75
+ /** Exclude insights with these tags (URL-scoped). */
76
+ excludeTags?: string[];
77
+ /**
78
+ * Author identifier for the current user.
79
+ * Used to populate the "Me" option in the author filter.
80
+ */
81
+ author?: string;
82
+ enabledVisualizationClassesUrls?: string[];
83
+ selectedInsightId?: string;
84
+ enableDescriptions?: boolean;
85
+ metadataTimeZone?: string;
86
+ enableSemanticSearch?: boolean;
87
+ maxHeight?: number;
88
+ width?: number;
89
+ searchQuery: string;
90
+ onSearchChange: (query: string) => void;
91
+ sortBy: InsightPickerSortBy;
92
+ sortDirection: InsightPickerSortDirection;
93
+ onSortChange: (sortBy: InsightPickerSortBy, sortDirection: InsightPickerSortDirection) => void;
94
+ /** Selected author IDs. Empty array = "All". */
95
+ authorFilter: string[];
96
+ onAuthorFilterChange: (authorIds: string[]) => void;
97
+ /** Selected tag values. Empty array = "All". */
98
+ tagFilter: string[];
99
+ onTagFilterChange: (tagIds: string[]) => void;
100
+ onSelect: (insightRef: ObjRef, item: IInsightPickerItem) => void;
101
+ onDescriptionPanelOpen?: (description: string) => void;
102
+ onItemActivate?: (item: IInsightPickerItem, sourceInsight?: IInsight) => void;
103
+ menuActions?: IInsightPickerMenuAction[];
104
+ renderMenu?: (props: IInsightPickerMenuProps) => ReactNode;
105
+ renderItem?: (props: IInsightPickerRenderItemProps) => ReactElement;
106
+ }
107
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/insightPicker/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ // (C) 2026 GoodData Corporation
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/insightPicker/types.ts"],"names":[],"mappings":"AAAA,gCAAgC"}
@@ -0,0 +1,17 @@
1
+ import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
2
+ import { type IUiAsyncTableFilterOption } from "@gooddata/sdk-ui-kit";
3
+ /**
4
+ * Loads author and tag filter options from the analytics catalog API.
5
+ * Uses the same endpoints as the analytical catalog component:
6
+ * - getCreatedBy() → list of users who created objects
7
+ * - getTags() → list of available tags
8
+ *
9
+ * @internal
10
+ */
11
+ export declare function useInsightPickerFilters(backend: IAnalyticalBackend, workspace: string, currentAuthor?: string): {
12
+ authorOptions: IUiAsyncTableFilterOption[];
13
+ tagOptions: IUiAsyncTableFilterOption[];
14
+ authorsLoaded: boolean;
15
+ tagsLoaded: boolean;
16
+ };
17
+ //# sourceMappingURL=useInsightPickerFilters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInsightPickerFilters.d.ts","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerFilters.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAItE;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACnC,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM;;;;;EA+CzB"}
@@ -0,0 +1,55 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useMemo } from "react";
3
+ import { useIntl } from "react-intl";
4
+ import { useCancelablePromise } from "@gooddata/sdk-ui";
5
+ import { messages } from "./messages.js";
6
+ /**
7
+ * Loads author and tag filter options from the analytics catalog API.
8
+ * Uses the same endpoints as the analytical catalog component:
9
+ * - getCreatedBy() → list of users who created objects
10
+ * - getTags() → list of available tags
11
+ *
12
+ * @internal
13
+ */
14
+ export function useInsightPickerFilters(backend, workspace, currentAuthor) {
15
+ const intl = useIntl();
16
+ // --- Load authors ---
17
+ const { result: createdByResult, status: authorsStatus } = useCancelablePromise({
18
+ promise: () => backend.workspace(workspace).genAI().getAnalyticsCatalog().getCreatedBy(),
19
+ onError: (error) => console.error("Failed to load authors:", error),
20
+ }, [backend, workspace]);
21
+ const meLabel = intl.formatMessage(messages.filterCreatedByMe);
22
+ const authorOptions = useMemo(() => {
23
+ const users = createdByResult?.users ?? [];
24
+ const sorted = sortUsers(users);
25
+ return sorted.map((user) => ({
26
+ value: user.login,
27
+ label: user.login === currentAuthor ? meLabel : (user.fullName ?? user.login),
28
+ }));
29
+ }, [createdByResult?.users, currentAuthor, meLabel]);
30
+ // --- Load tags ---
31
+ const { result: tagsResult, status: tagsStatus } = useCancelablePromise({
32
+ promise: () => backend.workspace(workspace).genAI().getAnalyticsCatalog().getTags(),
33
+ onError: (error) => console.error("Failed to load tags:", error),
34
+ }, [backend, workspace]);
35
+ const tagOptions = useMemo(() => {
36
+ const tags = tagsResult?.tags ?? [];
37
+ return [...tags]
38
+ .sort((a, b) => a.localeCompare(b))
39
+ .map((tag) => ({
40
+ value: tag,
41
+ label: tag,
42
+ }));
43
+ }, [tagsResult?.tags]);
44
+ const authorsLoaded = authorsStatus === "success";
45
+ const tagsLoaded = tagsStatus === "success";
46
+ return { authorOptions, tagOptions, authorsLoaded, tagsLoaded };
47
+ }
48
+ function sortUsers(users) {
49
+ return [...users].sort((a, b) => {
50
+ const nameA = (a.fullName ?? a.login).toLowerCase();
51
+ const nameB = (b.fullName ?? b.login).toLowerCase();
52
+ return nameA.localeCompare(nameB);
53
+ });
54
+ }
55
+ //# sourceMappingURL=useInsightPickerFilters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInsightPickerFilters.js","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerFilters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type IInsight } from "@gooddata/sdk-model";
2
+ import { type IInsightPickerItem } from "./types.js";
3
+ interface IUseInsightPickerHybridSearchOptions {
4
+ insights: IInsight[];
5
+ searchQuery: string;
6
+ onSearchChange: (query: string) => void;
7
+ enableSemanticSearch?: boolean;
8
+ includeTags?: string[];
9
+ excludeTags?: string[];
10
+ }
11
+ /**
12
+ * Wraps useHybridSearch with the insight-specific item mapping and search state sync.
13
+ *
14
+ * @internal
15
+ */
16
+ export declare function useInsightPickerHybridSearch({ insights, searchQuery, onSearchChange, enableSemanticSearch, includeTags, excludeTags }: IUseInsightPickerHybridSearchOptions): {
17
+ searchState: import("@gooddata/sdk-ui-semantic-search").ISearchState;
18
+ semanticSearchState: import("@gooddata/sdk-ui-semantic-search").ISemanticSearchState;
19
+ searchEntries: IInsightPickerItem[];
20
+ displayItems: IInsightPickerItem[];
21
+ isSearching: boolean;
22
+ handleSearchChange: (query: string) => void;
23
+ };
24
+ export {};
25
+ //# sourceMappingURL=useInsightPickerHybridSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInsightPickerHybridSearch.d.ts","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerHybridSearch.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,QAAQ,EAWhB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAsBrD,UAAU,oCAAoC;IAC1C,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,EACzC,QAAQ,EACR,WAAW,EACX,cAAc,EACd,oBAA2B,EAC3B,WAAW,EACX,WAAW,EACd,EAAE,oCAAoC;;;;;;;EAuEtC"}
@@ -0,0 +1,66 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useCallback, useEffect, useMemo, useRef } from "react";
3
+ import { insightCreated, insightId, insightIsLocked, insightSummary, insightTitle, insightUpdated, insightUri, insightVisualizationUrl, uriRef, } from "@gooddata/sdk-model";
4
+ import { customMatcher, useHybridSearch, } from "@gooddata/sdk-ui-semantic-search";
5
+ const SEMANTIC_SEARCH_OBJECT_TYPES = ["visualization"];
6
+ const insightItemBuilder = (item, { ref }) => ({
7
+ ref,
8
+ title: item.title,
9
+ description: item.description,
10
+ identifier: item.id,
11
+ isLocked: false,
12
+ created: item.createdAt,
13
+ updated: item.modifiedAt ?? item.createdAt,
14
+ visualizationUrl: item.visualizationUrl ?? "",
15
+ });
16
+ /**
17
+ * Wraps useHybridSearch with the insight-specific item mapping and search state sync.
18
+ *
19
+ * @internal
20
+ */
21
+ export function useInsightPickerHybridSearch({ insights, searchQuery, onSearchChange, enableSemanticSearch = true, includeTags, excludeTags, }) {
22
+ const searchEntries = useMemo(() => insights.map((insight) => ({
23
+ ref: uriRef(insightUri(insight)),
24
+ title: insightTitle(insight),
25
+ description: insightSummary(insight),
26
+ identifier: insightId(insight),
27
+ uri: insightUri(insight),
28
+ isLocked: insightIsLocked(insight),
29
+ created: insightCreated(insight),
30
+ updated: insightUpdated(insight),
31
+ visualizationUrl: insightVisualizationUrl(insight),
32
+ })), [insights]);
33
+ const matcher = useMemo(() => customMatcher(["title", "description", "identifier"]), []);
34
+ const { searchState, semanticSearchState, search: hybridSearch, onSearchQueryChange: setHybridSearchQuery, } = useHybridSearch({
35
+ objectTypes: SEMANTIC_SEARCH_OBJECT_TYPES,
36
+ allowSematicSearch: enableSemanticSearch,
37
+ itemBuilder: insightItemBuilder,
38
+ includeTags,
39
+ excludeTags,
40
+ matcher,
41
+ });
42
+ // Sync controlled search query into hybrid search on mount
43
+ const initializedSearch = useRef(false);
44
+ useEffect(() => {
45
+ if (!initializedSearch.current) {
46
+ initializedSearch.current = true;
47
+ setHybridSearchQuery(searchQuery);
48
+ }
49
+ }, [searchQuery, setHybridSearchQuery]);
50
+ const handleSearchChange = useCallback((query) => {
51
+ setHybridSearchQuery(query);
52
+ onSearchChange(query);
53
+ }, [setHybridSearchQuery, onSearchChange]);
54
+ const isSearching = searchState.query !== "";
55
+ const { searchItems, searchRelatedItems } = useMemo(() => hybridSearch({ items: searchEntries }), [hybridSearch, searchEntries]);
56
+ const displayItems = useMemo(() => (isSearching ? [...searchItems, ...searchRelatedItems] : searchEntries), [isSearching, searchEntries, searchItems, searchRelatedItems]);
57
+ return {
58
+ searchState,
59
+ semanticSearchState,
60
+ searchEntries,
61
+ displayItems,
62
+ isSearching,
63
+ handleSearchChange,
64
+ };
65
+ }
66
+ //# sourceMappingURL=useInsightPickerHybridSearch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInsightPickerHybridSearch.js","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerHybridSearch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type InsightPickerSortBy, type InsightPickerSortDirection } from "./types.js";
2
+ /**
3
+ * Managed state for the InsightPicker component.
4
+ * Use this hook in the consumer to own all picker state so it persists
5
+ * across open/close cycles. Spread the returned object into `<InsightPicker>`.
6
+ *
7
+ * @param author - current user identifier; when provided, authorFilter defaults to [author] ("Me")
8
+ * @internal
9
+ */
10
+ export declare function useInsightPickerState(author?: string): {
11
+ searchQuery: string;
12
+ onSearchChange: import("react").Dispatch<import("react").SetStateAction<string>>;
13
+ sortBy: InsightPickerSortBy;
14
+ sortDirection: InsightPickerSortDirection;
15
+ onSortChange: (newSortBy: InsightPickerSortBy, newDirection: InsightPickerSortDirection) => void;
16
+ authorFilter: string[];
17
+ onAuthorFilterChange: (nextAuthorFilter: string[]) => void;
18
+ tagFilter: string[];
19
+ onTagFilterChange: import("react").Dispatch<import("react").SetStateAction<string[]>>;
20
+ };
21
+ //# sourceMappingURL=useInsightPickerState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInsightPickerState.d.ts","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerState.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAEvF;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,MAAM;;;;;;;;;;EA6CpD"}
@@ -0,0 +1,49 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ /**
4
+ * Managed state for the InsightPicker component.
5
+ * Use this hook in the consumer to own all picker state so it persists
6
+ * across open/close cycles. Spread the returned object into `<InsightPicker>`.
7
+ *
8
+ * @param author - current user identifier; when provided, authorFilter defaults to [author] ("Me")
9
+ * @internal
10
+ */
11
+ export function useInsightPickerState(author) {
12
+ const [searchQuery, setSearchQuery] = useState("");
13
+ const [sortBy, setSortBy] = useState("lastModified");
14
+ const [sortDirection, setSortDirection] = useState("desc");
15
+ const [authorFilter, setAuthorFilter] = useState(author ? [author] : []);
16
+ const [tagFilter, setTagFilter] = useState([]);
17
+ // Latches to true on first user change and stays latched — once the user picks their own
18
+ // filter, we never re-apply the "Me" default, even if `author` arrives late.
19
+ const isAuthorFilterModified = useRef(false);
20
+ useEffect(() => {
21
+ if (!author || isAuthorFilterModified.current) {
22
+ return;
23
+ }
24
+ const isAuthorFilterInSync = authorFilter.length === 1 && authorFilter[0] === author;
25
+ if (!isAuthorFilterInSync) {
26
+ setAuthorFilter([author]);
27
+ }
28
+ }, [author, authorFilter]);
29
+ const onAuthorFilterChange = useCallback((nextAuthorFilter) => {
30
+ isAuthorFilterModified.current = true;
31
+ setAuthorFilter(nextAuthorFilter);
32
+ }, []);
33
+ const onSortChange = useCallback((newSortBy, newDirection) => {
34
+ setSortBy(newSortBy);
35
+ setSortDirection(newDirection);
36
+ }, []);
37
+ return {
38
+ searchQuery,
39
+ onSearchChange: setSearchQuery,
40
+ sortBy,
41
+ sortDirection,
42
+ onSortChange,
43
+ authorFilter,
44
+ onAuthorFilterChange,
45
+ tagFilter,
46
+ onTagFilterChange: setTagFilter,
47
+ };
48
+ }
49
+ //# sourceMappingURL=useInsightPickerState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInsightPickerState.js","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerState.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjE;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAe,EAAE;IACnD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAsB,cAAc,CAAC,CAAC;IAC1E,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAA6B,MAAM,CAAC,CAAC;IACvF,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAW,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACnF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IACzD,2FAAyF;IACzF,6EAA6E;IAC7E,MAAM,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE7C,SAAS,CAAC,GAAG,EAAE,CAAC;QACZ,IAAI,CAAC,MAAM,IAAI,sBAAsB,CAAC,OAAO,EAAE,CAAC;YAC5C,OAAO;QACX,CAAC;QAED,MAAM,oBAAoB,GAAG,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;QACrF,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACxB,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9B,CAAC;IAAA,CACJ,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3B,MAAM,oBAAoB,GAAG,WAAW,CAAC,CAAC,gBAA0B,EAAE,EAAE,CAAC;QACrE,sBAAsB,CAAC,OAAO,GAAG,IAAI,CAAC;QACtC,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAAA,CACrC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,YAAY,GAAG,WAAW,CAC5B,CAAC,SAA8B,EAAE,YAAwC,EAAE,EAAE,CAAC;QAC1E,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAAA,CAClC,EACD,EAAE,CACL,CAAC;IAEF,OAAO;QACH,WAAW;QACX,cAAc,EAAE,cAAc;QAC9B,MAAM;QACN,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,oBAAoB;QACpB,SAAS;QACT,iBAAiB,EAAE,YAAY;KAClC,CAAC;AAAA,CACL"}
@@ -1,6 +1,16 @@
1
1
  import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
2
2
  import { type IInsight } from "@gooddata/sdk-model";
3
3
  import { type ITab } from "@gooddata/sdk-ui-kit";
4
+ /**
5
+ * Sort field for the insights paged list. Mirrors `InsightPickerSortBy` in the public API.
6
+ * @internal
7
+ */
8
+ export type InsightListSortBy = "lastModified" | "name";
9
+ /**
10
+ * Sort direction for the insights paged list.
11
+ * @internal
12
+ */
13
+ export type InsightListSortDirection = "asc" | "desc";
4
14
  /**
5
15
  * Tabs ids for insights paged list hook
6
16
  * @internal
@@ -20,6 +30,26 @@ export interface IUsePagedDropdownConfig {
20
30
  tabsIds: ITabsIds;
21
31
  tags?: string[];
22
32
  excludeTags?: string[];
33
+ /**
34
+ * Sort field. When omitted, defaults to the backend's default ordering
35
+ * (modifiedAt, createdAt, title — descending).
36
+ */
37
+ sortBy?: InsightListSortBy;
38
+ /**
39
+ * Sort direction. Defaults to "desc".
40
+ */
41
+ sortDirection?: InsightListSortDirection;
42
+ /**
43
+ * When provided, filters insights by these author IDs (createdBy).
44
+ * Replaces the tab-based author filtering.
45
+ */
46
+ createdByFilter?: string[];
47
+ /**
48
+ * When true, always includes createdBy/modifiedBy in the query response
49
+ * so author metadata is available on loaded insights.
50
+ * Only used by the enhanced insight picker — other consumers should leave this off.
51
+ */
52
+ includeAuthorInfo?: boolean;
23
53
  }
24
54
  /**
25
55
  * Result of useInsightPagedList hook
@@ -58,9 +88,11 @@ export interface IUsePagedDropdownResult {
58
88
  * @param tabsIds - tabs ids
59
89
  * @param tags - fetch only the insights with these tags
60
90
  * @param excludeTags - omit insights with these tags during fetch
91
+ * @param sortBy - sort field
92
+ * @param sortDirection - sort direction
61
93
  * @returns useInsightPagedList result
62
94
  *
63
95
  * @internal
64
96
  */
65
- export declare function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags }: IUsePagedDropdownConfig): IUsePagedDropdownResult;
97
+ export declare function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags, sortBy, sortDirection, createdByFilter, includeAuthorInfo }: IUsePagedDropdownConfig): IUsePagedDropdownResult;
66
98
  //# sourceMappingURL=useInsightPagedList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useInsightPagedList.d.ts","sourceRoot":"","sources":["../../../../src/internal/components/insightList/useInsightPagedList.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,kBAAkB,EAA2B,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAIjD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,OAAO,CAAC;KACxB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3E,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,IAAI,CAAC;CAC1B;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,OAAO,EACP,WAAW,EACX,MAAM,EACN,OAAO,EACP,IAAI,EACJ,WAAW,EACd,EAAE,uBAAuB,GAAG,uBAAuB,CAgNnD"}
1
+ {"version":3,"file":"useInsightPagedList.d.ts","sourceRoot":"","sources":["../../../../src/internal/components/insightList/useInsightPagedList.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,kBAAkB,EAA2B,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAIjD;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,MAAM,CAAC;AAExD;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,OAAO,CAAC;KACxB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3E,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,IAAI,CAAC;CAC1B;AAWD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,OAAO,EACP,WAAW,EACX,MAAM,EACN,OAAO,EACP,IAAI,EACJ,WAAW,EACX,MAAM,EACN,aAAsC,EACtC,eAAe,EACf,iBAAyB,EAC5B,EAAE,uBAAuB,GAAG,uBAAuB,CAsOnD"}
@@ -1,8 +1,14 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { useCallback, useRef, useState } from "react";
2
+ import { useCallback, useMemo, useRef, useState } from "react";
3
3
  import { debounce, isEmpty } from "lodash-es";
4
4
  const ITEMS_PER_PAGE = 50;
5
- const DEFAULT_INSIGHT_SORT = ["modifiedAt,createdAt,title,desc"];
5
+ const DEFAULT_SORT_DIRECTION = "desc";
6
+ function buildSorting(sortBy, direction) {
7
+ if (sortBy === "name") {
8
+ return [`title,${direction}`];
9
+ }
10
+ return [`modifiedAt,createdAt,title,${direction}`];
11
+ }
6
12
  /**
7
13
  * Hook to fetch insights paged list
8
14
  * @param backend - analytical backend
@@ -11,11 +17,13 @@ const DEFAULT_INSIGHT_SORT = ["modifiedAt,createdAt,title,desc"];
11
17
  * @param tabsIds - tabs ids
12
18
  * @param tags - fetch only the insights with these tags
13
19
  * @param excludeTags - omit insights with these tags during fetch
20
+ * @param sortBy - sort field
21
+ * @param sortDirection - sort direction
14
22
  * @returns useInsightPagedList result
15
23
  *
16
24
  * @internal
17
25
  */
18
- export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags, }) {
26
+ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags, sortBy, sortDirection = DEFAULT_SORT_DIRECTION, createdByFilter, includeAuthorInfo = false, }) {
19
27
  const [items, setItems] = useState([]);
20
28
  const [totalItemsCount, setTotalItemsCount] = useState(undefined);
21
29
  const [isLoading, setIsLoading] = useState(false);
@@ -26,6 +34,7 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
26
34
  const [selectedTabId, setSelectedTabId] = useState(tabsIds.my);
27
35
  const abortControllerRef = useRef(null);
28
36
  const initialLoadCompletedRef = useRef(false);
37
+ const sorting = useMemo(() => buildSorting(sortBy, sortDirection), [sortBy, sortDirection]);
29
38
  const totalItems = totalItemsCount ?? items.length;
30
39
  const hasNextPage = totalItems > items.length;
31
40
  const skeletonItemsCount = hasNextPage ? Math.min(ITEMS_PER_PAGE, totalItems - items.length) : 0;
@@ -58,17 +67,24 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
58
67
  .getInsightsQuery()
59
68
  .withSize(ITEMS_PER_PAGE)
60
69
  .withPage(page)
61
- .withSorting(DEFAULT_INSIGHT_SORT);
70
+ .withSorting(sorting);
62
71
  const searchedTitle = searchValue || undefined;
63
- const searchedAuthor = tabId === tabsIds.my && isEmpty(searchValue) ? author : undefined;
64
- if (searchedAuthor) {
72
+ // When includeAuthorInfo is true (picker mode), only use the explicit createdByFilter.
73
+ // Otherwise fall back to the legacy tab-based author filtering.
74
+ const searchedAuthor = !includeAuthorInfo && tabId === tabsIds.my && isEmpty(searchValue) ? author : undefined;
75
+ const effectiveCreatedBy = createdByFilter?.length
76
+ ? createdByFilter
77
+ : searchedAuthor
78
+ ? [searchedAuthor]
79
+ : undefined;
80
+ if (includeAuthorInfo || effectiveCreatedBy) {
65
81
  query.withInclude(["createdBy", "modifiedBy"]);
66
82
  }
67
83
  const filter = {
68
84
  ...((tags?.length ?? 0) > 0 ? { tags } : {}),
69
85
  ...((excludeTags?.length ?? 0) > 0 ? { excludeTags } : {}),
70
86
  ...(searchedTitle ? { title: searchedTitle } : {}),
71
- ...(searchedAuthor ? { createdBy: [searchedAuthor] } : {}),
87
+ ...(effectiveCreatedBy ? { createdBy: effectiveCreatedBy } : {}),
72
88
  };
73
89
  if (Object.keys(filter).length > 0) {
74
90
  query.withFilter(filter);
@@ -99,7 +115,7 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
99
115
  .getInsightsQuery()
100
116
  .withSize(ITEMS_PER_PAGE)
101
117
  .withPage(0)
102
- .withSorting(DEFAULT_INSIGHT_SORT);
118
+ .withSorting(sorting);
103
119
  const allFilter = {
104
120
  ...((tags?.length ?? 0) > 0 ? { tags } : {}),
105
121
  ...((excludeTags?.length ?? 0) > 0 ? { excludeTags } : {}),
@@ -129,7 +145,17 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
129
145
  setIsNextPageLoading(false);
130
146
  }
131
147
  }
132
- }, [backend, workspaceId, author, tabsIds, tags, excludeTags]);
148
+ }, [
149
+ backend,
150
+ workspaceId,
151
+ author,
152
+ tabsIds,
153
+ tags,
154
+ excludeTags,
155
+ sorting,
156
+ createdByFilter,
157
+ includeAuthorInfo,
158
+ ]);
133
159
  const loadNextPage = useCallback(() => {
134
160
  if (!hasNextPage || isNextPageLoading || isLoading) {
135
161
  return;
@@ -163,9 +189,11 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
163
189
  }, []);
164
190
  const shouldLoadNextPage = useCallback((lastItemIndex, itemsCount) => lastItemIndex >= itemsCount - 5, []);
165
191
  const loadInitialItems = useCallback(() => {
192
+ setCurrentPage(0);
166
193
  void fetchItems({ page: 0, search: "", tabId: undefined, resetItems: true });
167
194
  }, [fetchItems]);
168
195
  const resetItems = useCallback(() => {
196
+ setCurrentPage(0);
169
197
  void fetchItems({ page: 0, search: search, tabId: selectedTabId, resetItems: true });
170
198
  }, [fetchItems, search, selectedTabId]);
171
199
  return {