@gooddata/sdk-ui-semantic-search 10.8.0-alpha.1 → 10.8.0-alpha.10
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.
- package/esm/ResultsItem.d.ts +6 -5
- package/esm/ResultsItem.d.ts.map +1 -1
- package/esm/ResultsItem.js +34 -9
- package/esm/ResultsItem.js.map +1 -1
- package/esm/{SearchResults.d.ts → SearchResultsDropdownList.d.ts} +6 -6
- package/esm/SearchResultsDropdownList.d.ts.map +1 -0
- package/esm/SearchResultsDropdownList.js +16 -0
- package/esm/SearchResultsDropdownList.js.map +1 -0
- package/esm/SemanticSearch.d.ts +28 -0
- package/esm/SemanticSearch.d.ts.map +1 -1
- package/esm/SemanticSearch.js +17 -14
- package/esm/SemanticSearch.js.map +1 -1
- package/esm/hooks/index.d.ts +1 -0
- package/esm/hooks/index.d.ts.map +1 -1
- package/esm/hooks/index.js +1 -0
- package/esm/hooks/index.js.map +1 -1
- package/esm/hooks/useListSelector.d.ts +7 -0
- package/esm/hooks/useListSelector.d.ts.map +1 -0
- package/esm/hooks/useListSelector.js +42 -0
- package/esm/hooks/useListSelector.js.map +1 -0
- package/esm/hooks/useSemanticSearch.d.ts +7 -3
- package/esm/hooks/useSemanticSearch.d.ts.map +1 -1
- package/esm/hooks/useSemanticSearch.js +15 -5
- package/esm/hooks/useSemanticSearch.js.map +1 -1
- package/esm/internal/HeaderSearchButton.d.ts +8 -0
- package/esm/internal/HeaderSearchButton.d.ts.map +1 -0
- package/esm/internal/HeaderSearchButton.js +37 -0
- package/esm/internal/HeaderSearchButton.js.map +1 -0
- package/esm/internal/SearchOverlay.d.ts +41 -0
- package/esm/internal/SearchOverlay.d.ts.map +1 -0
- package/esm/internal/SearchOverlay.js +64 -0
- package/esm/internal/SearchOverlay.js.map +1 -0
- package/esm/internal/SearchResultsList.d.ts +26 -0
- package/esm/internal/SearchResultsList.d.ts.map +1 -0
- package/esm/internal/SearchResultsList.js +16 -0
- package/esm/internal/SearchResultsList.js.map +1 -0
- package/esm/internal.d.ts +8 -0
- package/esm/internal.d.ts.map +1 -0
- package/esm/internal.js +9 -0
- package/esm/internal.js.map +1 -0
- package/esm/sdk-ui-semantic-search.d.ts +42 -2
- package/esm/utils/getUIPath.d.ts +14 -0
- package/esm/utils/getUIPath.d.ts.map +1 -0
- package/esm/utils/getUIPath.js +37 -0
- package/esm/utils/getUIPath.js.map +1 -0
- package/package.json +9 -7
- package/styles/css/internal.css +158 -0
- package/styles/css/internal.css.map +1 -0
- package/styles/css/main.css +43 -3
- package/styles/css/main.css.map +1 -1
- package/styles/scss/internal.scss +102 -0
- package/styles/scss/main.scss +50 -4
- package/esm/SearchResults.d.ts.map +0 -1
- package/esm/SearchResults.js +0 -43
- package/esm/SearchResults.js.map +0 -1
package/esm/ResultsItem.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { ISemanticSearchResultItemWithUrl } from "@gooddata/sdk-model";
|
|
3
|
+
export declare const ITEM_HEIGHT = 45;
|
|
3
4
|
/**
|
|
4
5
|
* Props for the ResultsItem component.
|
|
5
6
|
* @internal
|
|
@@ -8,7 +9,7 @@ export type ResultsItemProps = {
|
|
|
8
9
|
/**
|
|
9
10
|
* The item to render.
|
|
10
11
|
*/
|
|
11
|
-
item:
|
|
12
|
+
item: ISemanticSearchResultItemWithUrl;
|
|
12
13
|
/**
|
|
13
14
|
* The height of the item.
|
|
14
15
|
*/
|
|
@@ -20,15 +21,15 @@ export type ResultsItemProps = {
|
|
|
20
21
|
/**
|
|
21
22
|
* Whether the item is selected.
|
|
22
23
|
*/
|
|
23
|
-
|
|
24
|
+
active: boolean;
|
|
24
25
|
/**
|
|
25
26
|
* Callback to trigger when the item is hovered.
|
|
26
27
|
*/
|
|
27
|
-
onHover: () => void;
|
|
28
|
+
onHover: (item: ISemanticSearchResultItemWithUrl) => void;
|
|
28
29
|
/**
|
|
29
30
|
* Callback to trigger when the item is clicked.
|
|
30
31
|
*/
|
|
31
|
-
|
|
32
|
+
onSelect: (item: ISemanticSearchResultItemWithUrl) => void;
|
|
32
33
|
};
|
|
33
34
|
/**
|
|
34
35
|
* A single result item in the search results.
|
package/esm/ResultsItem.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResultsItem.d.ts","sourceRoot":"","sources":["../src/ResultsItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ResultsItem.d.ts","sourceRoot":"","sources":["../src/ResultsItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAKvE,eAAO,MAAM,WAAW,KAAK,CAAC;AAG9B;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC3B;;OAEG;IACH,IAAI,EAAE,gCAAgC,CAAC;IACvC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,gCAAgC,KAAK,IAAI,CAAC;IAC1D;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,gCAAgC,KAAK,IAAI,CAAC;CAC9D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA8ClD,CAAC"}
|
package/esm/ResultsItem.js
CHANGED
|
@@ -1,29 +1,54 @@
|
|
|
1
1
|
// (C) 2024 GoodData Corporation
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import classnames from "classnames";
|
|
4
|
-
import { Icon, Typography } from "@gooddata/sdk-ui-kit";
|
|
4
|
+
import { Bubble, BubbleHoverTrigger, EllipsisText, Icon, Typography } from "@gooddata/sdk-ui-kit";
|
|
5
|
+
import { useTheme } from "@gooddata/sdk-ui-theme-provider";
|
|
6
|
+
import { FormattedMessage } from "react-intl";
|
|
7
|
+
export const ITEM_HEIGHT = 45;
|
|
8
|
+
const BUBBLE_ALIGN_POINTS = [{ align: "bc tr", offset: { x: 2, y: -4 } }];
|
|
5
9
|
/**
|
|
6
10
|
* A single result item in the search results.
|
|
7
11
|
* @internal
|
|
8
12
|
*/
|
|
9
|
-
export const ResultsItem = ({ item, onHover,
|
|
13
|
+
export const ResultsItem = ({ item, onHover, onSelect, active }) => {
|
|
14
|
+
const theme = useTheme();
|
|
10
15
|
const onMouseEnter = (e) => {
|
|
11
16
|
// Prevent multiple triggers
|
|
12
17
|
if (e.target !== e.currentTarget) {
|
|
13
18
|
return;
|
|
14
19
|
}
|
|
15
|
-
onHover();
|
|
20
|
+
onHover(item);
|
|
21
|
+
};
|
|
22
|
+
const onClick = (e) => {
|
|
23
|
+
e.preventDefault();
|
|
24
|
+
onSelect(item);
|
|
16
25
|
};
|
|
17
26
|
const className = classnames({
|
|
18
27
|
"gd-semantic-search__results-item": true,
|
|
19
|
-
"gd-semantic-search__results-item--
|
|
28
|
+
"gd-semantic-search__results-item--active": active,
|
|
20
29
|
});
|
|
21
30
|
// Use mouse enter with the target check instead of hover to prevent multiple triggers
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
React.createElement("
|
|
25
|
-
React.createElement("
|
|
26
|
-
React.createElement(
|
|
31
|
+
return (React.createElement("a", { className: className, onMouseEnter: onMouseEnter, onClick: onClick, href: item.url },
|
|
32
|
+
React.createElement("span", { className: "gd-semantic-search__results-item__icon" }, renderItemIcon(item)),
|
|
33
|
+
React.createElement("span", { className: "gd-semantic-search__results-item__text" }, item.title),
|
|
34
|
+
React.createElement("span", { className: "gd-semantic-search__results-item__details" },
|
|
35
|
+
React.createElement(BubbleHoverTrigger, { eventsOnBubble: true },
|
|
36
|
+
React.createElement(Icon.QuestionMark, { color: theme?.palette?.complementary?.c7 ?? "#6D7680" }),
|
|
37
|
+
React.createElement(Bubble, { className: "bubble-light gd-semantic-search__bubble", alignPoints: BUBBLE_ALIGN_POINTS, arrowStyle: { display: "none" } },
|
|
38
|
+
React.createElement("div", { className: "gd-semantic-search__results-item__details__contents" },
|
|
39
|
+
React.createElement(Typography, { tagName: "h3" }, item.title),
|
|
40
|
+
renderIfHasDescription(item),
|
|
41
|
+
React.createElement(FormattedMessage, { tagName: "h4", id: "semantic-search.id" }),
|
|
42
|
+
React.createElement(Typography, { tagName: "p" }, item.id)))))));
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Render the description if it is different from the title.
|
|
46
|
+
*/
|
|
47
|
+
const renderIfHasDescription = (item) => {
|
|
48
|
+
if (item.description && item.description !== item.title) {
|
|
49
|
+
return React.createElement(EllipsisText, { maxLines: 7, text: item.description });
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
27
52
|
};
|
|
28
53
|
/**
|
|
29
54
|
* Pick an icon according to the item type.
|
package/esm/ResultsItem.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResultsItem.js","sourceRoot":"","sources":["../src/ResultsItem.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"ResultsItem.js","sourceRoot":"","sources":["../src/ResultsItem.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { ISemanticSearchResultItemWithUrl } from "@gooddata/sdk-model";
|
|
3
3
|
/**
|
|
4
4
|
* Search results props.
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
type
|
|
7
|
+
type SearchResultsDropdownListProps = {
|
|
8
8
|
/**
|
|
9
9
|
* Search result items.
|
|
10
10
|
*/
|
|
11
|
-
searchResults:
|
|
11
|
+
searchResults: ISemanticSearchResultItemWithUrl[];
|
|
12
12
|
/**
|
|
13
13
|
* Loading flag.
|
|
14
14
|
*/
|
|
@@ -24,12 +24,12 @@ type SearchResultsProps = {
|
|
|
24
24
|
/**
|
|
25
25
|
* Callback for item selection.
|
|
26
26
|
*/
|
|
27
|
-
onSelect: (item:
|
|
27
|
+
onSelect: (item: ISemanticSearchResultItemWithUrl) => void;
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
30
30
|
* A dropdown list with the search results.
|
|
31
31
|
* @internal
|
|
32
32
|
*/
|
|
33
|
-
export declare const
|
|
33
|
+
export declare const SearchResultsDropdownList: React.FC<SearchResultsDropdownListProps>;
|
|
34
34
|
export {};
|
|
35
|
-
//# sourceMappingURL=
|
|
35
|
+
//# sourceMappingURL=SearchResultsDropdownList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchResultsDropdownList.d.ts","sourceRoot":"","sources":["../src/SearchResultsDropdownList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAKvE;;;GAGG;AACH,KAAK,8BAA8B,GAAG;IAClC;;OAEG;IACH,aAAa,EAAE,gCAAgC,EAAE,CAAC;IAClD;;OAEG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,gCAAgC,KAAK,IAAI,CAAC;CAC9D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,8BAA8B,CA8B9E,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// (C) 2024 GoodData Corporation
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { DropdownList } from "@gooddata/sdk-ui-kit";
|
|
4
|
+
import { ITEM_HEIGHT, ResultsItem } from "./ResultsItem.js";
|
|
5
|
+
import { useListSelector } from "./hooks/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* A dropdown list with the search results.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export const SearchResultsDropdownList = ({ searchResults, searchLoading, isMobile, width, onSelect, }) => {
|
|
11
|
+
const [active, setActive] = useListSelector(searchResults, onSelect);
|
|
12
|
+
return (React.createElement(DropdownList, { width: width, isMobile: isMobile, isLoading: searchLoading, itemHeight: ITEM_HEIGHT, renderItem: ({ item, width, height }) => {
|
|
13
|
+
return (React.createElement(ResultsItem, { onHover: setActive, onSelect: onSelect, active: item === active, item: item, width: width, height: height }));
|
|
14
|
+
}, items: searchResults }));
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=SearchResultsDropdownList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchResultsDropdownList.js","sourceRoot":"","sources":["../src/SearchResultsDropdownList.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AA6BnD;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAA6C,CAAC,EAChF,aAAa,EACb,aAAa,EACb,QAAQ,EACR,KAAK,EACL,QAAQ,GACX,EAAE,EAAE;IACD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,eAAe,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAErE,OAAO,CACH,oBAAC,YAAY,IACT,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,WAAW,EACvB,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;YACpC,OAAO,CACH,oBAAC,WAAW,IACR,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,IAAI,KAAK,MAAM,EACvB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,GAChB,CACL,CAAC;QACN,CAAC,EACD,KAAK,EAAE,aAAa,GACtB,CACL,CAAC;AACN,CAAC,CAAC"}
|
package/esm/SemanticSearch.d.ts
CHANGED
|
@@ -6,14 +6,42 @@ import { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
|
6
6
|
* @alpha
|
|
7
7
|
*/
|
|
8
8
|
export type SemanticSearchCoreProps = {
|
|
9
|
+
/**
|
|
10
|
+
* An analytical backend to use for the search. Can be omitted and taken from context.
|
|
11
|
+
*/
|
|
9
12
|
backend?: IAnalyticalBackend;
|
|
13
|
+
/**
|
|
14
|
+
* A workspace to search in. Can be omitted and taken from context.
|
|
15
|
+
*/
|
|
10
16
|
workspace?: string;
|
|
17
|
+
/**
|
|
18
|
+
* A function called when the user selects an item from the search results.
|
|
19
|
+
*/
|
|
11
20
|
onSelect: (item: ISemanticSearchResultItem) => void;
|
|
21
|
+
/**
|
|
22
|
+
* A function called when an error occurs during the search.
|
|
23
|
+
*/
|
|
12
24
|
onError?: (errorMessage: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Additional CSS class for the component.
|
|
27
|
+
*/
|
|
13
28
|
className?: string;
|
|
29
|
+
/**
|
|
30
|
+
* A list of object types to search for.
|
|
31
|
+
*/
|
|
14
32
|
objectTypes?: GenAISemanticSearchType[];
|
|
33
|
+
/**
|
|
34
|
+
* A flag to enable deep search, i.e. search dashboard by their contents.
|
|
35
|
+
*/
|
|
15
36
|
deepSearch?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* A limit of search results to return.
|
|
39
|
+
*/
|
|
16
40
|
limit?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Placeholder text for the search input.
|
|
43
|
+
*/
|
|
44
|
+
placeholder?: string;
|
|
17
45
|
};
|
|
18
46
|
/**
|
|
19
47
|
* Semantic search component props.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SemanticSearch.d.ts","sourceRoot":"","sources":["../src/SemanticSearch.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAIzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAClC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACpD,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"SemanticSearch.d.ts","sourceRoot":"","sources":["../src/SemanticSearch.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAIzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAClC;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACpD;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACxC;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAiGF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,GAAG;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAMxD,CAAC"}
|
package/esm/SemanticSearch.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { useDebouncedState, Input, Dropdown } from "@gooddata/sdk-ui-kit";
|
|
4
4
|
import { IntlWrapper } from "@gooddata/sdk-ui";
|
|
5
|
-
import {
|
|
5
|
+
import { SearchResultsDropdownList } from "./SearchResultsDropdownList.js";
|
|
6
6
|
import { useSemanticSearch } from "./hooks/index.js";
|
|
7
7
|
import classnames from "classnames";
|
|
8
8
|
/**
|
|
@@ -14,11 +14,11 @@ const DEBOUNCE = 300;
|
|
|
14
14
|
* Semantic search component core.
|
|
15
15
|
* @alpha
|
|
16
16
|
*/
|
|
17
|
-
const SemanticSearchCore = ({ backend, workspace, onSelect, onError, objectTypes, deepSearch = false, limit = 10, className, }) => {
|
|
17
|
+
const SemanticSearchCore = ({ backend, workspace, onSelect, onError, objectTypes, deepSearch = false, limit = 10, className, placeholder, }) => {
|
|
18
18
|
// Input value handling
|
|
19
19
|
const [value, setValue, searchTerm] = useDebouncedState("", DEBOUNCE);
|
|
20
20
|
// Search results
|
|
21
|
-
const {
|
|
21
|
+
const { searchStatus, searchResults, searchError } = useSemanticSearch({
|
|
22
22
|
backend,
|
|
23
23
|
workspace,
|
|
24
24
|
searchTerm,
|
|
@@ -35,23 +35,26 @@ const SemanticSearchCore = ({ backend, workspace, onSelect, onError, objectTypes
|
|
|
35
35
|
setWidth(input.offsetWidth);
|
|
36
36
|
}
|
|
37
37
|
}, []);
|
|
38
|
-
const onItemSelect = React.useCallback((item) => {
|
|
39
|
-
onSelect(item);
|
|
40
|
-
inputRef.current?.inputNodeRef?.inputNodeRef?.blur();
|
|
41
|
-
}, [onSelect]);
|
|
42
38
|
// Report errors
|
|
43
39
|
React.useEffect(() => {
|
|
44
|
-
if (onError &&
|
|
40
|
+
if (onError && searchStatus === "error") {
|
|
45
41
|
onError(searchError);
|
|
46
42
|
}
|
|
47
|
-
}, [onError, searchError]);
|
|
48
|
-
return (React.createElement(Dropdown, { className: classnames("gd-semantic-search", className),
|
|
49
|
-
|
|
43
|
+
}, [onError, searchError, searchStatus]);
|
|
44
|
+
return (React.createElement(Dropdown, { className: classnames("gd-semantic-search", className), ignoreClicksOnByClass: [
|
|
45
|
+
".gd-bubble",
|
|
46
|
+
".gd-semantic-search__results-item",
|
|
47
|
+
".gd-semantic-search__input",
|
|
48
|
+
], renderBody: ({ isMobile, closeDropdown }) => {
|
|
49
|
+
if (!searchResults.length && searchStatus !== "loading") {
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
|
-
return (React.createElement(
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
return (React.createElement(SearchResultsDropdownList, { width: width, isMobile: isMobile, searchResults: searchResults, searchLoading: searchStatus === "loading", onSelect: (item) => {
|
|
53
|
+
onSelect(item);
|
|
54
|
+
closeDropdown();
|
|
55
|
+
} }));
|
|
56
|
+
}, renderButton: ({ openDropdown }) => {
|
|
57
|
+
return (React.createElement(Input, { className: "gd-semantic-search__input", ref: inputRef, placeholder: placeholder, isSearch: true, clearOnEsc: true, value: value, onChange: (e) => setValue(String(e)), onFocus: openDropdown }));
|
|
55
58
|
} }));
|
|
56
59
|
};
|
|
57
60
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SemanticSearch.js","sourceRoot":"","sources":["../src/SemanticSearch.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"SemanticSearch.js","sourceRoot":"","sources":["../src/SemanticSearch.tsx"],"names":[],"mappings":"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"}
|
package/esm/hooks/index.d.ts
CHANGED
package/esm/hooks/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAEA,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAEA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
|
package/esm/hooks/index.js
CHANGED
package/esm/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This hook provides keyboard navigation for a list of items. It listens to ArrowUp, ArrowDown and Enter keys and
|
|
3
|
+
* calls the onSelect callback when Enter is pressed.
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const useListSelector: <T>(items: T[], onSelect: (item: T) => void) => [T, (item: T) => void];
|
|
7
|
+
//# sourceMappingURL=useListSelector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListSelector.d.ts","sourceRoot":"","sources":["../../src/hooks/useListSelector.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,eAAe,yCAA+C,IAAI,sBAyCb,IAAI,CACrE,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// (C) 2024 GoodData Corporation
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* This hook provides keyboard navigation for a list of items. It listens to ArrowUp, ArrowDown and Enter keys and
|
|
5
|
+
* calls the onSelect callback when Enter is pressed.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export const useListSelector = (items, onSelect) => {
|
|
9
|
+
const [selected, setSelected] = React.useState(0);
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
setSelected(0);
|
|
12
|
+
}, [items]);
|
|
13
|
+
const setSelectedItem = React.useCallback((item) => {
|
|
14
|
+
setSelected(Math.max(Math.min(items.indexOf(item), items.length - 1), 0));
|
|
15
|
+
}, [items]);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
const listener = (event) => {
|
|
18
|
+
if (["ArrowDown", "ArrowUp", "Enter"].indexOf(event.key) === -1)
|
|
19
|
+
return;
|
|
20
|
+
const setIndex = (index) => setSelected(Math.max(Math.min(index, items.length - 1), 0));
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
event.stopImmediatePropagation();
|
|
23
|
+
switch (event.key) {
|
|
24
|
+
case "ArrowDown":
|
|
25
|
+
setIndex(selected + 1);
|
|
26
|
+
break;
|
|
27
|
+
case "ArrowUp":
|
|
28
|
+
setIndex(selected - 1);
|
|
29
|
+
break;
|
|
30
|
+
case "Enter":
|
|
31
|
+
onSelect(items[selected]);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
// Listen to keyboard events while the component is mounted
|
|
35
|
+
document.addEventListener("keydown", listener);
|
|
36
|
+
return () => {
|
|
37
|
+
document.removeEventListener("keydown", listener);
|
|
38
|
+
};
|
|
39
|
+
}, [items, onSelect, selected]);
|
|
40
|
+
return [items[selected], setSelectedItem];
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=useListSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListSelector.js","sourceRoot":"","sources":["../../src/hooks/useListSelector.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAI,KAAe,EAAE,QAA2B,EAAE,EAAE;IAC/E,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAS,CAAC,CAAC,CAAC;IAC1D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,WAAW,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACZ,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CACrC,CAAC,IAAO,EAAE,EAAE;QACR,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC,EACD,CAAC,KAAK,CAAC,CACV,CAAC;IAEF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,MAAM,QAAQ,GAAG,CAAC,KAAoB,EAAE,EAAE;YACtC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAAE,OAAO;YAExE,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAEhG,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,KAAK,CAAC,wBAAwB,EAAE,CAAC;YAEjC,QAAQ,KAAK,CAAC,GAAG,EAAE,CAAC;gBAChB,KAAK,WAAW;oBACZ,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;oBACvB,MAAM;gBACV,KAAK,SAAS;oBACV,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;oBACvB,MAAM;gBACV,KAAK,OAAO;oBACR,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClC,CAAC;QACL,CAAC,CAAC;QAEF,2DAA2D;QAC3D,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAE/C,OAAO,GAAG,EAAE;YACR,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACtD,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,eAAe,CAA2B,CAAC;AACxE,CAAC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ISemanticSearchResultItemWithUrl, GenAISemanticSearchType } from "@gooddata/sdk-model";
|
|
2
2
|
import { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
3
3
|
/**
|
|
4
4
|
* The result of the semantic search hook.
|
|
@@ -7,8 +7,12 @@ import { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
|
7
7
|
export type SemanticSearchInputResult = {
|
|
8
8
|
/**
|
|
9
9
|
* Flag indicating whether the search is in progress.
|
|
10
|
+
* - idle - means we did not search yet
|
|
11
|
+
* - loading - means we are currently searching
|
|
12
|
+
* - error - means the search failed
|
|
13
|
+
* - success - means the search succeeded
|
|
10
14
|
*/
|
|
11
|
-
|
|
15
|
+
searchStatus: "idle" | "loading" | "error" | "success";
|
|
12
16
|
/**
|
|
13
17
|
* Error message if the search failed.
|
|
14
18
|
*/
|
|
@@ -16,7 +20,7 @@ export type SemanticSearchInputResult = {
|
|
|
16
20
|
/**
|
|
17
21
|
* The search results.
|
|
18
22
|
*/
|
|
19
|
-
searchResults:
|
|
23
|
+
searchResults: ISemanticSearchResultItemWithUrl[];
|
|
20
24
|
};
|
|
21
25
|
/**
|
|
22
26
|
* Input parameters for the semantic search hook.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSemanticSearch.d.ts","sourceRoot":"","sources":["../../src/hooks/useSemanticSearch.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"useSemanticSearch.d.ts","sourceRoot":"","sources":["../../src/hooks/useSemanticSearch.ts"],"names":[],"mappings":"AAGA,OAAO,EAEH,gCAAgC,EAChC,uBAAuB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACpC;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACvD;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,aAAa,EAAE,gCAAgC,EAAE,CAAC;CACrD,CAAC;AAWF;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAClC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACxC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAIF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,wEAO3B,uBAAuB,KAAG,yBA+D5B,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// (C) 2024 GoodData Corporation
|
|
2
2
|
import { useState, useEffect } from "react";
|
|
3
3
|
import { useBackendStrict, useWorkspaceStrict } from "@gooddata/sdk-ui";
|
|
4
|
+
import { getUIPath } from "../utils/getUIPath.js";
|
|
4
5
|
/**
|
|
5
6
|
* Default state of the semantic search hook.
|
|
6
7
|
*/
|
|
7
8
|
const DEFAULT_STATE = {
|
|
8
|
-
|
|
9
|
+
searchStatus: "idle",
|
|
9
10
|
searchError: "",
|
|
10
11
|
searchResults: [],
|
|
11
12
|
};
|
|
@@ -28,7 +29,7 @@ export const useSemanticSearch = ({ searchTerm, objectTypes = DEFAULT_OBJECT_TYP
|
|
|
28
29
|
setState((oldState) => ({
|
|
29
30
|
// Keep the previous state of results/error, only update the loading flag
|
|
30
31
|
...oldState,
|
|
31
|
-
|
|
32
|
+
searchStatus: "loading",
|
|
32
33
|
}));
|
|
33
34
|
// Construct the query
|
|
34
35
|
let qb = effectiveBackend
|
|
@@ -52,9 +53,9 @@ export const useSemanticSearch = ({ searchTerm, objectTypes = DEFAULT_OBJECT_TYP
|
|
|
52
53
|
})
|
|
53
54
|
.then((res) => {
|
|
54
55
|
setState({
|
|
55
|
-
|
|
56
|
+
searchStatus: "success",
|
|
56
57
|
searchError: "",
|
|
57
|
-
searchResults: res.results,
|
|
58
|
+
searchResults: res.results.map(withUrl(effectiveWorkspace)),
|
|
58
59
|
});
|
|
59
60
|
})
|
|
60
61
|
.catch((e) => {
|
|
@@ -62,7 +63,7 @@ export const useSemanticSearch = ({ searchTerm, objectTypes = DEFAULT_OBJECT_TYP
|
|
|
62
63
|
// Ignore Aborted error
|
|
63
64
|
return;
|
|
64
65
|
setState({
|
|
65
|
-
|
|
66
|
+
searchStatus: "error",
|
|
66
67
|
searchError: errorMessage(e),
|
|
67
68
|
searchResults: [],
|
|
68
69
|
});
|
|
@@ -82,4 +83,13 @@ const errorMessage = (e) => {
|
|
|
82
83
|
}
|
|
83
84
|
return String(e);
|
|
84
85
|
};
|
|
86
|
+
/**
|
|
87
|
+
* Enrich the result item with UI URL.
|
|
88
|
+
*/
|
|
89
|
+
const withUrl = (workspaceId) => (item) => {
|
|
90
|
+
return {
|
|
91
|
+
...item,
|
|
92
|
+
url: getUIPath(item.type, item.id, workspaceId),
|
|
93
|
+
};
|
|
94
|
+
};
|
|
85
95
|
//# sourceMappingURL=useSemanticSearch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSemanticSearch.js","sourceRoot":"","sources":["../../src/hooks/useSemanticSearch.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useSemanticSearch.js","sourceRoot":"","sources":["../../src/hooks/useSemanticSearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { SearchOverlayProps } from "./SearchOverlay.js";
|
|
3
|
+
export type HeaderSearchButtonProps = SearchOverlayProps;
|
|
4
|
+
export declare const HeaderSearchButtonCore: React.FC<HeaderSearchButtonProps>;
|
|
5
|
+
export declare const HeaderSearchButton: React.FC<import("react-intl").WithIntlProps<SearchOverlayProps>> & {
|
|
6
|
+
WrappedComponent: React.ComponentType<SearchOverlayProps>;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=HeaderSearchButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeaderSearchButton.d.ts","sourceRoot":"","sources":["../../src/internal/HeaderSearchButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAiB,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAKvE,MAAM,MAAM,uBAAuB,GAAG,kBAAkB,CAAC;AAEzD,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAsDpE,CAAC;AAEF,eAAO,MAAM,kBAAkB;;CAAqC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// (C) 2007-2024 GoodData Corporation
|
|
2
|
+
import React from "react";
|
|
3
|
+
import cx from "classnames";
|
|
4
|
+
import { FormattedMessage, injectIntl } from "react-intl";
|
|
5
|
+
import { Button, Overlay } from "@gooddata/sdk-ui-kit";
|
|
6
|
+
import { SearchOverlay } from "./SearchOverlay.js";
|
|
7
|
+
const ALIGN_POINTS = [{ align: "br tr" }];
|
|
8
|
+
export const HeaderSearchButtonCore = ({ onSelect, ...overlayProps }) => {
|
|
9
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
10
|
+
const classNames = cx("gd-header-measure", "gd-header-button", "gd-header-search", { "is-open": isOpen });
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
const shortcutHandler = (event) => {
|
|
13
|
+
if (event.key === "k" && (event.ctrlKey || event.metaKey)) {
|
|
14
|
+
setIsOpen(true);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
if (!isOpen) {
|
|
18
|
+
document.addEventListener("keydown", shortcutHandler);
|
|
19
|
+
}
|
|
20
|
+
return () => {
|
|
21
|
+
document.removeEventListener("keydown", shortcutHandler);
|
|
22
|
+
};
|
|
23
|
+
}, [isOpen]);
|
|
24
|
+
const handleSelect = (item) => {
|
|
25
|
+
onSelect(item);
|
|
26
|
+
setIsOpen(false);
|
|
27
|
+
};
|
|
28
|
+
return (React.createElement(Button, { title: overlayProps.intl.formatMessage({ id: "gs.header.search" }), className: classNames, onClick: () => setIsOpen(true) },
|
|
29
|
+
React.createElement("span", { className: "gd-icon-header-search" }),
|
|
30
|
+
React.createElement("span", { className: "gd-header-search-label" },
|
|
31
|
+
React.createElement(FormattedMessage, { id: "gs.header.search" })),
|
|
32
|
+
isOpen ? (React.createElement(Overlay, { isModal: false, alignTo: ".gd-header-search", alignPoints: ALIGN_POINTS, closeOnEscape: true, closeOnOutsideClick: true, closeOnParentScroll: false, closeOnMouseDrag: false, onClose: () => setIsOpen(false), ignoreClicksOnByClass: [".gd-bubble", ".gd-semantic-search__results-item"] },
|
|
33
|
+
React.createElement("div", { className: "gd-dialog gd-dropdown overlay gd-header-search-dropdown" },
|
|
34
|
+
React.createElement(SearchOverlay, { onSelect: handleSelect, ...overlayProps })))) : null));
|
|
35
|
+
};
|
|
36
|
+
export const HeaderSearchButton = injectIntl(HeaderSearchButtonCore);
|
|
37
|
+
//# sourceMappingURL=HeaderSearchButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeaderSearchButton.js","sourceRoot":"","sources":["../../src/internal/HeaderSearchButton.tsx"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAsB,MAAM,oBAAoB,CAAC;AAGvE,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAI1C,MAAM,CAAC,MAAM,sBAAsB,GAAsC,CAAC,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,EAAE,EAAE;IACvG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,EAAE,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAE1G,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,MAAM,eAAe,GAAG,CAAC,KAAoB,EAAE,EAAE;YAC7C,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxD,SAAS,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,GAAG,EAAE;YACR,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAC7D,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,YAAY,GAAG,CAAC,IAAsC,EAAE,EAAE;QAC5D,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,SAAS,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,OAAO,CACH,oBAAC,MAAM,IACH,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,kBAAkB,EAAE,CAAC,EAClE,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;QAE9B,8BAAM,SAAS,EAAC,uBAAuB,GAAQ;QAC/C,8BAAM,SAAS,EAAC,wBAAwB;YACpC,oBAAC,gBAAgB,IAAC,EAAE,EAAC,kBAAkB,GAAG,CACvC;QACN,MAAM,CAAC,CAAC,CAAC,CACN,oBAAC,OAAO,IACJ,OAAO,EAAE,KAAK,EACd,OAAO,EAAC,mBAAmB,EAC3B,WAAW,EAAE,YAAY,EACzB,aAAa,QACb,mBAAmB,QACnB,mBAAmB,EAAE,KAAK,EAC1B,gBAAgB,EAAE,KAAK,EACvB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAC/B,qBAAqB,EAAE,CAAC,YAAY,EAAE,mCAAmC,CAAC;YAE1E,6BAAK,SAAS,EAAC,yDAAyD;gBACpE,oBAAC,aAAa,IAAC,QAAQ,EAAE,YAAY,KAAM,YAAY,GAAI,CACzD,CACA,CACb,CAAC,CAAC,CAAC,IAAI,CACH,CACZ,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
3
|
+
import { GenAISemanticSearchType, ISemanticSearchResultItemWithUrl } from "@gooddata/sdk-model";
|
|
4
|
+
import { WrappedComponentProps } from "react-intl";
|
|
5
|
+
/**
|
|
6
|
+
* Props for the SemanticSearchOverlay component.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export type SearchOverlayProps = WrappedComponentProps & {
|
|
10
|
+
/**
|
|
11
|
+
* A function called when the user selects an item from the search results.
|
|
12
|
+
*/
|
|
13
|
+
onSelect: (item: ISemanticSearchResultItemWithUrl) => void;
|
|
14
|
+
/**
|
|
15
|
+
* An analytical backend to use for the search. Can be omitted and taken from context.
|
|
16
|
+
*/
|
|
17
|
+
backend?: IAnalyticalBackend;
|
|
18
|
+
/**
|
|
19
|
+
* A workspace to search in. Can be omitted and taken from context.
|
|
20
|
+
*/
|
|
21
|
+
workspace?: string;
|
|
22
|
+
/**
|
|
23
|
+
* A list of object types to search for.
|
|
24
|
+
*/
|
|
25
|
+
objectTypes?: GenAISemanticSearchType[];
|
|
26
|
+
/**
|
|
27
|
+
* A flag to enable deep search, i.e. search dashboard by their contents.
|
|
28
|
+
*/
|
|
29
|
+
deepSearch?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* A limit of search results to return.
|
|
32
|
+
*/
|
|
33
|
+
limit?: number;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* A component that allows users to search for insights, metrics, attributes, and other objects using semantic search.
|
|
37
|
+
* The internal version is meant to be used in an overlay inside the Header.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export declare const SearchOverlay: React.FC<SearchOverlayProps>;
|
|
41
|
+
//# sourceMappingURL=SearchOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchOverlay.d.ts","sourceRoot":"","sources":["../../src/internal/SearchOverlay.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAEhG,OAAO,EAAoB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAerE;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,qBAAqB,GAAG;IACrD;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,gCAAgC,KAAK,IAAI,CAAC;IAC3D;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACxC;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6EtD,CAAC"}
|