@redocly/theme 0.49.0 → 0.49.1

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.
@@ -46,7 +46,8 @@ const SpinnerLoader_1 = require("../../components/Loaders/SpinnerLoader");
46
46
  const SettingsIcon_1 = require("../../icons/SettingsIcon/SettingsIcon");
47
47
  const AiStarsIcon_1 = require("../../icons/AiStarsIcon/AiStarsIcon");
48
48
  function SearchDialog({ onClose, className }) {
49
- const { useTranslate, useCurrentProduct, useSearch, useProducts, useAiSearch } = (0, hooks_1.useThemeHooks)();
49
+ const { useTranslate, useCurrentProduct, useSearch, useProducts, useAiSearch, useTelemetry } = (0, hooks_1.useThemeHooks)();
50
+ const telemetry = useTelemetry();
50
51
  const products = useProducts();
51
52
  const currentProduct = useCurrentProduct();
52
53
  const [product, setProduct] = (0, react_1.useState)(currentProduct);
@@ -67,7 +68,7 @@ function SearchDialog({ onClose, className }) {
67
68
  onClose();
68
69
  }
69
70
  };
70
- const mapItem = (item, index) => {
71
+ const mapItem = (item, index, results) => {
71
72
  var _a;
72
73
  let itemProduct;
73
74
  if (!product && item.document.product) {
@@ -77,7 +78,15 @@ function SearchDialog({ onClose, className }) {
77
78
  ? { name: resolvedProduct.name, icon: resolvedProduct.icon }
78
79
  : undefined;
79
80
  }
80
- return react_1.default.createElement(SearchItem_1.SearchItem, { key: `${index}-${item.document.id}`, item: item, product: itemProduct });
81
+ return (react_1.default.createElement(SearchItem_1.SearchItem, { key: `${index}-${item.document.id}`, item: item, product: itemProduct, onClick: () => {
82
+ telemetry.send('search_result_clicked', {
83
+ query,
84
+ url: item.document.url,
85
+ total_results: results.length,
86
+ index,
87
+ search_engine: mode,
88
+ });
89
+ } }));
81
90
  };
82
91
  const showLoadMore = (groupKey, currentCount = 0) => {
83
92
  const groupFacet = facets.find((facet) => facet.field === groupField);
@@ -4,11 +4,12 @@ type ActiveItem<T> = T & {
4
4
  };
5
5
  export type SearchItemProps = {
6
6
  item: ActiveItem<SearchItemData>;
7
+ onClick?: VoidFunction;
7
8
  product?: {
8
9
  name: string;
9
10
  icon?: string;
10
11
  };
11
12
  className?: string;
12
13
  };
13
- export declare function SearchItem({ item, className, product }: SearchItemProps): JSX.Element;
14
+ export declare function SearchItem({ onClick, item, className, product }: SearchItemProps): JSX.Element;
14
15
  export {};
@@ -35,7 +35,7 @@ const Image_1 = require("../../components/Image/Image");
35
35
  const SearchHighlight_1 = require("../../components/Search/SearchHighlight");
36
36
  const Badge_1 = require("../../components/Badge/Badge");
37
37
  const utils_1 = require("../../core/utils");
38
- function SearchItem({ item, className, product }) {
38
+ function SearchItem({ onClick, item, className, product }) {
39
39
  var _a, _b, _c, _d;
40
40
  const ref = (0, react_1.useRef)();
41
41
  (0, react_1.useEffect)(() => {
@@ -47,7 +47,7 @@ function SearchItem({ item, className, product }) {
47
47
  const { document, highlight } = item;
48
48
  const parameter = highlight.parameters && highlight.parameters.length ? highlight.parameters[0] : null;
49
49
  const shouldShowPath = document.path && ((_a = document.path) === null || _a === void 0 ? void 0 : _a.length) > 1;
50
- return (react_1.default.createElement(SearchItemWrapper, { className: className, to: document.url, tabIndex: 0, innerRef: ref, "data-component-name": "Search/SearchItem" },
50
+ return (react_1.default.createElement(SearchItemWrapper, { className: className, to: document.url, onClick: onClick, tabIndex: 0, innerRef: ref, "data-component-name": "Search/SearchItem" },
51
51
  react_1.default.createElement(SearchItemHeader, null,
52
52
  product && (react_1.default.createElement(SearchItemProductTag, { "data-testid": "search-item-product-tag" },
53
53
  react_1.default.createElement(Image_1.Image, { src: product.icon }),
@@ -121,5 +121,5 @@ export type L10nConfig = {
121
121
  name: string;
122
122
  }[];
123
123
  };
124
- type TelemetryEvent = 'search_opened' | 'client_error_caught' | 'breadcrumb_clicked' | 'color_mode_switched' | 'sidebar_item_clicked' | 'sidebar_item_expanded' | 'sidebar_item_collapsed' | 'edit_page_link_clicked' | 'code_snippet_copied' | 'code_snippet_reported' | 'feedback_sent' | 'navbar_menu_item_clicked' | 'login_button_clicked' | 'login_provider_button_clicked' | 'logout_menu_item_clicked' | 'logo_clicked' | 'toc_item_clicked' | 'version_switched' | 'catalog_filter_changed' | 'catalog_item_clicked' | 'scorecard_link_clicked' | 'markdown_anchor_link_clicked' | 'back_to_catalog_button_clicked' | 'sidebar_drilldown_back_button_clicked' | 'footer_item_clicked' | 'request_api_access_button_clicked' | 'sidebar_samples_button_clicked' | 'change_layout_button_clicked' | 'version_picker_selection_change' | 'openapi_docs' | 'replay' | 'catalog_actions_button_clicked' | 'catalog_item_clicked' | 'filter_checkbox_toggled' | 'language_picker_locale_changed' | 'mobile_menu_button_close_clicked' | 'mobile_menu_button_open_clicked' | 'search_input_reset_button_clicked' | 'search_recent_remove_button_clicked' | 'product_picked';
124
+ type TelemetryEvent = 'search_opened' | 'client_error_caught' | 'breadcrumb_clicked' | 'color_mode_switched' | 'sidebar_item_clicked' | 'sidebar_item_expanded' | 'sidebar_item_collapsed' | 'edit_page_link_clicked' | 'code_snippet_copied' | 'code_snippet_reported' | 'feedback_sent' | 'navbar_menu_item_clicked' | 'login_button_clicked' | 'login_provider_button_clicked' | 'logout_menu_item_clicked' | 'logo_clicked' | 'toc_item_clicked' | 'version_switched' | 'catalog_filter_changed' | 'catalog_item_clicked' | 'scorecard_link_clicked' | 'markdown_anchor_link_clicked' | 'back_to_catalog_button_clicked' | 'sidebar_drilldown_back_button_clicked' | 'footer_item_clicked' | 'request_api_access_button_clicked' | 'sidebar_samples_button_clicked' | 'change_layout_button_clicked' | 'version_picker_selection_change' | 'openapi_docs' | 'replay' | 'catalog_actions_button_clicked' | 'catalog_item_clicked' | 'filter_checkbox_toggled' | 'language_picker_locale_changed' | 'mobile_menu_button_close_clicked' | 'mobile_menu_button_open_clicked' | 'search_input_reset_button_clicked' | 'search_recent_remove_button_clicked' | 'product_picked' | 'search_result_clicked';
125
125
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.49.0",
3
+ "version": "0.49.1",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -87,7 +87,7 @@
87
87
  "timeago.js": "4.0.2",
88
88
  "i18next": "22.4.15",
89
89
  "nprogress": "0.2.0",
90
- "@redocly/config": "0.20.2"
90
+ "@redocly/config": "0.20.3"
91
91
  },
92
92
  "scripts": {
93
93
  "watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
@@ -27,7 +27,9 @@ export type SearchDialogProps = {
27
27
  };
28
28
 
29
29
  export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Element {
30
- const { useTranslate, useCurrentProduct, useSearch, useProducts, useAiSearch } = useThemeHooks();
30
+ const { useTranslate, useCurrentProduct, useSearch, useProducts, useAiSearch, useTelemetry } =
31
+ useThemeHooks();
32
+ const telemetry = useTelemetry();
31
33
  const products = useProducts();
32
34
  const currentProduct = useCurrentProduct();
33
35
  const [product, setProduct] = useState(currentProduct);
@@ -69,7 +71,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
69
71
  }
70
72
  };
71
73
 
72
- const mapItem = (item: SearchItemData, index: number) => {
74
+ const mapItem = (item: SearchItemData, index: number, results: SearchItemData[]) => {
73
75
  let itemProduct;
74
76
  if (!product && item.document.product) {
75
77
  const folder = item.document.product?.folder;
@@ -80,7 +82,22 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
80
82
  ? { name: resolvedProduct.name, icon: resolvedProduct.icon }
81
83
  : undefined;
82
84
  }
83
- return <SearchItem key={`${index}-${item.document.id}`} item={item} product={itemProduct} />;
85
+ return (
86
+ <SearchItem
87
+ key={`${index}-${item.document.id}`}
88
+ item={item}
89
+ product={itemProduct}
90
+ onClick={() => {
91
+ telemetry.send('search_result_clicked', {
92
+ query,
93
+ url: item.document.url,
94
+ total_results: results.length,
95
+ index,
96
+ search_engine: mode,
97
+ });
98
+ }}
99
+ />
100
+ );
84
101
  };
85
102
 
86
103
  const showLoadMore = (groupKey: string, currentCount: number = 0) => {
@@ -13,6 +13,7 @@ import { trimText } from '@redocly/theme/core/utils';
13
13
  type ActiveItem<T> = T & { active?: boolean };
14
14
  export type SearchItemProps = {
15
15
  item: ActiveItem<SearchItemData>;
16
+ onClick?: VoidFunction;
16
17
  product?: {
17
18
  name: string;
18
19
  icon?: string;
@@ -20,7 +21,7 @@ export type SearchItemProps = {
20
21
  className?: string;
21
22
  };
22
23
 
23
- export function SearchItem({ item, className, product }: SearchItemProps): JSX.Element {
24
+ export function SearchItem({ onClick, item, className, product }: SearchItemProps): JSX.Element {
24
25
  const ref = useRef<HTMLAnchorElement>();
25
26
 
26
27
  useEffect(() => {
@@ -39,6 +40,7 @@ export function SearchItem({ item, className, product }: SearchItemProps): JSX.E
39
40
  <SearchItemWrapper
40
41
  className={className}
41
42
  to={document.url}
43
+ onClick={onClick}
42
44
  tabIndex={0}
43
45
  innerRef={ref}
44
46
  data-component-name="Search/SearchItem"
@@ -173,4 +173,5 @@ type TelemetryEvent =
173
173
  | 'mobile_menu_button_open_clicked'
174
174
  | 'search_input_reset_button_clicked'
175
175
  | 'search_recent_remove_button_clicked'
176
- | 'product_picked';
176
+ | 'product_picked'
177
+ | 'search_result_clicked';