@redocly/theme 0.62.0-next.5 → 0.62.0-next.6

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/lib/components/Banner/Banner.js +19 -1
  2. package/lib/components/Banner/variables.js +1 -0
  3. package/lib/components/Breadcrumbs/BreadcrumbDropdown.js +8 -5
  4. package/lib/components/Breadcrumbs/Breadcrumbs.js +24 -15
  5. package/lib/components/Buttons/AIAssistantButton.js +6 -3
  6. package/lib/components/Catalog/CatalogEntities.js +10 -8
  7. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.js +13 -11
  8. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +7 -5
  9. package/lib/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.js +9 -7
  10. package/lib/components/CatalogClassic/CatalogClassicInfoBlock.js +1 -1
  11. package/lib/components/CodeBlock/CodeBlockControls.js +3 -1
  12. package/lib/components/Filter/FilterCheckboxes.js +1 -1
  13. package/lib/components/LanguagePicker/LanguagePicker.js +1 -1
  14. package/lib/components/Markdown/Markdown.js +2 -2
  15. package/lib/components/Menu/MenuItem.js +7 -4
  16. package/lib/components/Navbar/NavbarItem.js +1 -1
  17. package/lib/components/Search/SearchAiMessage.js +8 -5
  18. package/lib/components/Search/SearchDialog.js +37 -22
  19. package/lib/core/hooks/search/use-search-dialog.js +2 -2
  20. package/lib/core/hooks/use-color-switcher.js +3 -1
  21. package/lib/core/hooks/use-page-actions.js +15 -5
  22. package/lib/core/hooks/use-product-picker.js +1 -1
  23. package/lib/markdoc/components/Cards/Card.js +1 -0
  24. package/lib/markdoc/components/Heading/Heading.js +34 -2
  25. package/package.json +2 -2
  26. package/src/components/Banner/Banner.tsx +23 -1
  27. package/src/components/Banner/variables.ts +1 -0
  28. package/src/components/Breadcrumbs/BreadcrumbDropdown.tsx +8 -5
  29. package/src/components/Breadcrumbs/Breadcrumbs.tsx +24 -15
  30. package/src/components/Buttons/AIAssistantButton.tsx +6 -3
  31. package/src/components/Catalog/CatalogEntities.tsx +10 -8
  32. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.tsx +13 -11
  33. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +7 -5
  34. package/src/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.tsx +9 -7
  35. package/src/components/CatalogClassic/CatalogClassicInfoBlock.tsx +3 -1
  36. package/src/components/CodeBlock/CodeBlockControls.tsx +3 -1
  37. package/src/components/Filter/FilterCheckboxes.tsx +1 -1
  38. package/src/components/LanguagePicker/LanguagePicker.tsx +1 -1
  39. package/src/components/Markdown/Markdown.tsx +2 -2
  40. package/src/components/Menu/MenuItem.tsx +7 -4
  41. package/src/components/Navbar/NavbarItem.tsx +3 -1
  42. package/src/components/Search/SearchAiMessage.tsx +8 -5
  43. package/src/components/Search/SearchDialog.tsx +37 -22
  44. package/src/core/hooks/search/use-search-dialog.ts +2 -2
  45. package/src/core/hooks/use-color-switcher.ts +3 -1
  46. package/src/core/hooks/use-page-actions.ts +30 -20
  47. package/src/core/hooks/use-product-picker.ts +1 -1
  48. package/src/markdoc/components/Cards/Card.tsx +1 -0
  49. package/src/markdoc/components/Heading/Heading.tsx +46 -4
@@ -37,9 +37,11 @@ exports.Banner = Banner;
37
37
  const react_1 = __importStar(require("react"));
38
38
  const styled_components_1 = __importStar(require("styled-components"));
39
39
  const hooks_1 = require("../../core/hooks");
40
+ const utils_1 = require("../../core/utils");
40
41
  const Markdown_1 = require("../../components/Markdown/Markdown");
41
42
  const CloseIcon_1 = require("../../icons/CloseIcon/CloseIcon");
42
43
  const Button_1 = require("../../components/Button/Button");
44
+ const ANIMATION_DURATION = 0.4;
43
45
  function setBannerHeight(height) {
44
46
  document.documentElement.style.setProperty('--banner-height', `${height}px`);
45
47
  }
@@ -86,6 +88,22 @@ function Banner({ className }) {
86
88
  setBannerHeight(height);
87
89
  };
88
90
  updateHeight();
91
+ if (window.location.hash) {
92
+ setTimeout(() => {
93
+ var _a;
94
+ const hash = window.location.hash;
95
+ const el = document.getElementById(hash.slice(1));
96
+ if (el) {
97
+ const navbar = (0, utils_1.getNavbarElement)();
98
+ const navbarHeight = (_a = navbar === null || navbar === void 0 ? void 0 : navbar.getBoundingClientRect().height) !== null && _a !== void 0 ? _a : 0;
99
+ const elementTop = el.getBoundingClientRect().top + window.scrollY;
100
+ const scrollPosition = elementTop - navbarHeight;
101
+ if (Math.abs(window.scrollY - scrollPosition) > 1) {
102
+ window.scrollTo({ top: scrollPosition });
103
+ }
104
+ }
105
+ }, ANIMATION_DURATION * 1000 + 100);
106
+ }
89
107
  const resizeObserver = new ResizeObserver(updateHeight);
90
108
  resizeObserver.observe(bannerElement);
91
109
  return () => {
@@ -148,7 +166,7 @@ const BannerWrapper = styled_components_1.default.div `
148
166
  width: 100%;
149
167
  z-index: var(--z-index-overlay);
150
168
  transform: ${({ $isVisible }) => ($isVisible ? 'translateY(0)' : 'translateY(-100%)')};
151
- transition: transform 0.4s ease-out;
169
+ transition: transform ${ANIMATION_DURATION}s ease-out;
152
170
  ${({ $color }) => $color &&
153
171
  (0, styled_components_1.css) `
154
172
  background-color: var(--banner-${$color}-bg-color);
@@ -6,6 +6,7 @@ exports.banner = (0, styled_components_1.css) `
6
6
  /**
7
7
  * @tokens Banner
8
8
  */
9
+ --banner-height: 0px; /* default 0px so calc formulas work on page load */
9
10
  --banner-button-size: 22px;
10
11
  --banner-button-padding: 3px; // @presenter Spacing
11
12
  --banner-button-font-size: var(--font-size-base);
@@ -66,11 +66,14 @@ function BreadcrumbDropdown({ children, label, items, onItemClick, className, })
66
66
  const translatedLabel = translate(item.labelTranslationKey, item.label);
67
67
  return (react_1.default.createElement(StyledDropdownMenuItem, { key: index, onAction: () => {
68
68
  onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item, index);
69
- telemetry.sendBreadcrumbClickedMessage({
70
- link: item.link,
71
- position: index + 1,
72
- totalBreadcrumbs: items.length,
73
- });
69
+ telemetry.sendBreadcrumbClickedMessage([
70
+ {
71
+ object: 'breadcrumb',
72
+ link: item.link,
73
+ position: index + 1,
74
+ totalBreadcrumbs: items.length,
75
+ },
76
+ ]);
74
77
  }, "$hasLink": hasLink, to: item.link, dataAttributes: !hasLink ? { 'aria-disabled': 'true' } : {} },
75
78
  react_1.default.createElement(DropdownContent, { "$isActive": isActive },
76
79
  react_1.default.createElement(BreadcrumbIcon_1.BreadcrumbIcon, { icon: item.icon }),
@@ -46,20 +46,26 @@ function Breadcrumbs(props) {
46
46
  ...currentItemSiblings,
47
47
  ];
48
48
  const translatedLabel = translate(breadcrumb.labelTranslationKey, breadcrumb.label);
49
- return (react_1.default.createElement(BreadcrumbDropdown_1.BreadcrumbDropdown, { label: translatedLabel, items: siblingsWithActive, onItemClick: (item, itemIdx) => telemetry.sendBreadcrumbClickedMessage({
50
- link: item.link,
51
- position: itemIdx + 1,
52
- totalBreadcrumbs: siblingsWithActive.length,
53
- }) },
49
+ return (react_1.default.createElement(BreadcrumbDropdown_1.BreadcrumbDropdown, { label: translatedLabel, items: siblingsWithActive, onItemClick: (item, itemIdx) => telemetry.sendBreadcrumbClickedMessage([
50
+ {
51
+ object: 'breadcrumb',
52
+ link: item.link,
53
+ position: itemIdx + 1,
54
+ totalBreadcrumbs: siblingsWithActive.length,
55
+ },
56
+ ]) },
54
57
  react_1.default.createElement(BreadcrumbIcon_1.BreadcrumbIcon, { icon: breadcrumb.icon }),
55
58
  (0, utils_1.trimText)(translatedLabel, constants_1.BREADCRUMB_MAX_LENGTH),
56
59
  react_1.default.createElement(GenericIcon_1.GenericIcon, { icon: "chevron-down" })));
57
60
  }
58
- return (react_1.default.createElement(Breadcrumb_1.Breadcrumb, { link: breadcrumb.link, label: translate(breadcrumb.labelTranslationKey, breadcrumb.label), isActive: isActive, icon: breadcrumb.icon, onClick: () => telemetry.sendBreadcrumbClickedMessage({
59
- link: breadcrumb.link,
60
- position: idx + 1,
61
- totalBreadcrumbs: breadcrumbs.length,
62
- }) }));
61
+ return (react_1.default.createElement(Breadcrumb_1.Breadcrumb, { link: breadcrumb.link, label: translate(breadcrumb.labelTranslationKey, breadcrumb.label), isActive: isActive, icon: breadcrumb.icon, onClick: () => telemetry.sendBreadcrumbClickedMessage([
62
+ {
63
+ object: 'breadcrumb',
64
+ link: breadcrumb.link,
65
+ position: idx + 1,
66
+ totalBreadcrumbs: breadcrumbs.length,
67
+ },
68
+ ]) }));
63
69
  };
64
70
  return (react_1.default.createElement(BreadcrumbsWrapper, { "data-component-name": "Breadcrumbs/Breadcrumbs", className: props.className }, items.map(({ breadcrumb, idx, isLast, inDropdown }) => {
65
71
  if (inDropdown)
@@ -69,11 +75,14 @@ function Breadcrumbs(props) {
69
75
  return (react_1.default.createElement(react_1.default.Fragment, { key: idx },
70
76
  renderBreadcrumb(breadcrumb, idx, isLast),
71
77
  react_1.default.createElement(BreadcrumbSeparator, null, "/"),
72
- react_1.default.createElement(BreadcrumbDropdown_1.BreadcrumbDropdown, { label: "...", items: collapsedBreadcrumbs, onItemClick: (item, itemIdx) => telemetry.sendBreadcrumbClickedMessage({
73
- link: item.link,
74
- position: itemIdx + 1,
75
- totalBreadcrumbs: breadcrumbs.length,
76
- }) }, "..."),
78
+ react_1.default.createElement(BreadcrumbDropdown_1.BreadcrumbDropdown, { label: "...", items: collapsedBreadcrumbs, onItemClick: (item, itemIdx) => telemetry.sendBreadcrumbClickedMessage([
79
+ {
80
+ object: 'breadcrumb',
81
+ link: item.link,
82
+ position: itemIdx + 1,
83
+ totalBreadcrumbs: breadcrumbs.length,
84
+ },
85
+ ]) }, "..."),
77
86
  react_1.default.createElement(BreadcrumbSeparator, null, "/")));
78
87
  }
79
88
  return (react_1.default.createElement(react_1.default.Fragment, { key: idx },
@@ -86,9 +86,12 @@ function AIAssistantButton() {
86
86
  const text = translate('aiAssistant.trigger', 'Ask AI');
87
87
  const handleOpen = () => {
88
88
  setIsOpen(true);
89
- telemetry.sendSearchAiOpenedMessage({
90
- method: 'ai_trigger_button',
91
- });
89
+ telemetry.sendSearchAiOpenedMessage([
90
+ {
91
+ object: 'search',
92
+ method: 'ai_trigger_button',
93
+ },
94
+ ]);
92
95
  };
93
96
  const handleClose = () => {
94
97
  setIsOpen(false);
@@ -64,14 +64,16 @@ function CatalogEntities(props) {
64
64
  }, props.initialEntitiesList);
65
65
  const onRowClick = (entity) => {
66
66
  if (searchQuery) {
67
- telemetry.sendCatalogEntitiesListSearchResultClickedMessage({
68
- id: entity.id,
69
- object: 'catalog_entity',
70
- uri: getEntityDetailsLink(entity),
71
- query: searchQuery,
72
- entityKey: entity.key,
73
- entityType: entity.type,
74
- });
67
+ telemetry.sendCatalogEntitiesListSearchResultClickedMessage([
68
+ {
69
+ id: entity.id,
70
+ object: 'catalog_entity',
71
+ uri: getEntityDetailsLink(entity),
72
+ query: searchQuery,
73
+ entityKey: entity.key,
74
+ entityType: entity.type,
75
+ },
76
+ ]);
75
77
  }
76
78
  };
77
79
  const shouldShowLoadMore = query.hasNextPage ||
@@ -19,17 +19,19 @@ function CatalogEntityRelationsTable({ entity, entitiesCatalogConfig, catalogCon
19
19
  });
20
20
  const onRowClick = (relatedEntity) => {
21
21
  if (searchQuery) {
22
- telemetry.sendCatalogEntitiesRelatedEntitiesListSearchResultClickMessage({
23
- id: relatedEntity.id,
24
- object: 'catalog_entity',
25
- uri: getEntityDetailsLink(relatedEntity),
26
- query: searchQuery,
27
- entityKey: entity.key,
28
- entityType: entity.type,
29
- relationType: constants_1.reverseRelationMap[relatedEntity.relationType],
30
- relatedEntityKey: relatedEntity.key,
31
- relatedEntityType: relatedEntity.type,
32
- });
22
+ telemetry.sendCatalogEntitiesRelatedEntitiesListSearchResultClickMessage([
23
+ {
24
+ id: relatedEntity.id,
25
+ object: 'catalog_entity',
26
+ uri: getEntityDetailsLink(relatedEntity),
27
+ query: searchQuery,
28
+ entityKey: entity.key,
29
+ entityType: entity.type,
30
+ relationType: constants_1.reverseRelationMap[relatedEntity.relationType],
31
+ relatedEntityKey: relatedEntity.key,
32
+ relatedEntityType: relatedEntity.type,
33
+ },
34
+ ]);
33
35
  }
34
36
  };
35
37
  return (react_1.default.createElement("div", { "data-component-name": "Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable" },
@@ -58,11 +58,13 @@ function CatalogEntitySchema({ entity, relatedEntity, catalogConfig, RedocSchema
58
58
  return (react_1.default.createElement(MetadataWrapper, { "data-component-name": "Catalog/CatalogEntity/CatalogEntityMetadata" },
59
59
  react_1.default.createElement(HeaderWrapper, null,
60
60
  react_1.default.createElement(Heading, null, translate('catalog.entity.schema.title')),
61
- !isGraphql && (react_1.default.createElement(CopyButton_1.CopyButton, { data: rawSchema, buttonText: "Copy Schema", type: "compound", variant: "secondary", iconPosition: "right", size: "medium", onCopyClick: () => telemetry.sendCatalogEntitiesCopyDataSchemaClickedMessage({
62
- id: entity.id,
63
- object: 'catalog_entity',
64
- uri: getEntityDetailsLink(entity),
65
- }) }))),
61
+ !isGraphql && (react_1.default.createElement(CopyButton_1.CopyButton, { data: rawSchema, buttonText: "Copy Schema", type: "compound", variant: "secondary", iconPosition: "right", size: "medium", onCopyClick: () => telemetry.sendCatalogEntitiesCopyDataSchemaClickedMessage([
62
+ {
63
+ id: entity.id,
64
+ object: 'catalog_entity',
65
+ uri: getEntityDetailsLink(entity),
66
+ },
67
+ ]) }))),
66
68
  react_1.default.createElement(SplitViewWrapper, null,
67
69
  react_1.default.createElement(SchemaContentWrapper, null, isGraphql && graphqlSDL && GraphqlTypeRenderer ? (react_1.default.createElement(GraphqlTypeRenderer, { sdl: graphqlSDL, typeName: entity.title })) : (react_1.default.createElement(StoreProvider, { definition: definition },
68
70
  react_1.default.createElement(RedocSchema, { schema: parsedSchema })))),
@@ -103,13 +103,15 @@ function CatalogFilterCheckboxes({ filter, filterValuesCasing, showCounter = tru
103
103
  const id = 'filter--' + filter.property + '--' + value;
104
104
  return (react_1.default.createElement(FilterCheckboxOption, { key: id, role: "link", onClick: () => {
105
105
  filter.toggleOption(value);
106
- telemetry.sendCatalogEntitiesFilterCheckboxToggledMessage({
107
- id: filter.property + '--' + value,
108
- object: 'checkbox',
109
- uri: window.location.href,
110
- category: filter.property,
111
- value: value,
112
- });
106
+ telemetry.sendCatalogEntitiesFilterCheckboxToggledMessage([
107
+ {
108
+ id: filter.property + '--' + value,
109
+ object: 'checkbox',
110
+ uri: window.location.href,
111
+ category: filter.property,
112
+ value: value,
113
+ },
114
+ ]);
113
115
  } },
114
116
  react_1.default.createElement(CheckboxIcon_1.CheckboxIcon, { checked: filter.selectedOptions instanceof Set
115
117
  ? filter.selectedOptions.has(value) ||
@@ -21,7 +21,7 @@ function ScorecardBadge(props) {
21
21
  const { useTelemetry } = (0, hooks_1.useThemeHooks)();
22
22
  const telemetry = useTelemetry();
23
23
  return (react_1.default.createElement(Link_1.Link, { to: slug },
24
- react_1.default.createElement(Tag_1.Tag, { onClick: () => telemetry.sendScorecardLinkClickedMessage({ action: 'click' }), withStatusDot: true, statusDotColor: `var(${colorVariable})` }, level)));
24
+ react_1.default.createElement(Tag_1.Tag, { onClick: () => telemetry.sendScorecardLinkClickedMessage([{ object: 'link', action: 'click' }]), withStatusDot: true, statusDotColor: `var(${colorVariable})` }, level)));
25
25
  }
26
26
  const CatalogInfoBlockWrapper = styled_components_1.default.div `
27
27
  position: relative;
@@ -54,7 +54,9 @@ function CodeBlockControls({ children, className, title, controls, tabs, dropdow
54
54
  (_a = copy === null || copy === void 0 ? void 0 : copy.onClick) === null || _a === void 0 ? void 0 : _a.call(copy);
55
55
  }
56
56
  else {
57
- telemetry.sendCopyCodeSnippetClickedMessage({ snippetType: 'copy' });
57
+ telemetry.sendCopyCodeSnippetClickedMessage([
58
+ { object: 'code_snippet', snippetType: 'copy' },
59
+ ]);
58
60
  }
59
61
  } }))) : null))) : null;
60
62
  return children || controls ? (react_1.default.createElement(ContainerWrapper, { "data-component-name": "CodeBlock/CodeBlockControls", className: className, "$isEmptyTitle": isEmptyTitle }, children ? children : defaultControls)) : null;
@@ -24,7 +24,7 @@ function FilterCheckboxes({ filter, filterValuesCasing, showCounter = true, }) {
24
24
  const id = 'filter--' + filter.property + '--' + value;
25
25
  return (react_1.default.createElement(FilterCheckboxOption, { key: id, role: "link", onClick: () => {
26
26
  filter.toggleOption(value);
27
- telemetry.sendFilterCheckboxToggledMessage({ id });
27
+ telemetry.sendFilterCheckboxToggledMessage([{ object: 'checkbox', id }]);
28
28
  } },
29
29
  react_1.default.createElement(CheckboxIcon_1.CheckboxIcon, { checked: filter.selectedOptions instanceof Set
30
30
  ? filter.selectedOptions.has(value) ||
@@ -26,7 +26,7 @@ function LanguagePicker(props) {
26
26
  onAction: () => {
27
27
  setLocale(locale.code);
28
28
  props.onChangeLanguage(locale.code);
29
- telemetry.sendLanguagePickerLocaleChangedMessage({ locale: locale.code });
29
+ telemetry.sendLanguagePickerLocaleChangedMessage([{ object: 'locale', locale: locale.code }]);
30
30
  },
31
31
  active: locale.code === currentLocale.code,
32
32
  suffix: locale.code === currentLocale.code && react_1.default.createElement(CheckmarkIcon_1.CheckmarkIcon, null),
@@ -77,7 +77,7 @@ exports.Markdown = styled_components_1.default.main.attrs(({ className }) => ({
77
77
  ${links_1.markdownLinksCss}
78
78
 
79
79
  a[name], [id] {
80
- scroll-margin-top: var(--navbar-height);
80
+ scroll-margin-top: calc(var(--navbar-height) + var(--banner-height));
81
81
  }
82
82
 
83
83
  img,
@@ -95,7 +95,7 @@ exports.Markdown = styled_components_1.default.main.attrs(({ className }) => ({
95
95
  font-family: var(--heading-font-family);
96
96
  position: relative;
97
97
 
98
- scroll-margin-top: var(--navbar-height);
98
+ scroll-margin-top: calc(var(--navbar-height) + var(--banner-height));
99
99
  }
100
100
 
101
101
  strong {
@@ -65,10 +65,13 @@ function MenuItem(props) {
65
65
  const hasChevron = isNested && !isDrilldown;
66
66
  const hasHttpTag = !!item.httpVerb || type === constants_1.MenuItemType.Operation;
67
67
  const handleOnClick = () => {
68
- telemetry.sendSidebarItemClickedMessage({
69
- label: item.label,
70
- type: item.type === 'link' || item.type === 'group' ? item.type : undefined,
71
- });
68
+ telemetry.sendSidebarItemClickedMessage([
69
+ {
70
+ object: 'sidebar_item',
71
+ label: item.label,
72
+ type: item.type === 'link' || item.type === 'group' ? item.type : undefined,
73
+ },
74
+ ]);
72
75
  onClick === null || onClick === void 0 ? void 0 : onClick();
73
76
  if (isNested) {
74
77
  handleExpand();
@@ -27,7 +27,7 @@ function NavbarItem({ navItem, className }) {
27
27
  const normalizedPath = (item.link ? (0, utils_1.removeTrailingSlash)(item.link) : item.link) || '';
28
28
  const pathWithPathPrefix = (0, utils_1.withPathPrefix)((0, utils_1.getPathnameForLocale)(normalizedPath, defaultLocale, currentLocale, locales));
29
29
  const isActive = (0, utils_1.removeTrailingSlash)(pathname) === (0, utils_1.removeTrailingSlash)(pathWithPathPrefix);
30
- const itemContent = (react_1.default.createElement(NavbarMenuItem, { as: item.link ? Link_1.Link : undefined, active: isActive, className: className, onClick: () => telemetry.sendNavbarMenuItemClickedMessage({ type: item.type }), external: item.external, target: item.target, to: item.link },
30
+ const itemContent = (react_1.default.createElement(NavbarMenuItem, { as: item.link ? Link_1.Link : undefined, active: isActive, className: className, onClick: () => telemetry.sendNavbarMenuItemClickedMessage([{ object: 'menu_item', type: item.type }]), external: item.external, target: item.target, to: item.link },
31
31
  react_1.default.createElement(NavbarIcon, { icon: item.icon, srcSet: item.srcSet }),
32
32
  react_1.default.createElement(NavbarLabel, { "data-translation-key": item.labelTranslationKey }, translate(item.labelTranslationKey, item.label)),
33
33
  item.external ? react_1.default.createElement(ExternalLinkIcon, { size: "10px" }) : null));
@@ -64,11 +64,14 @@ function SearchAiMessageComponent({ role, content, isThinking, resources, classN
64
64
  if (!messageId)
65
65
  return;
66
66
  try {
67
- telemetry.sendSearchAIFeedbackMessage({
68
- feedback: feedbackValue,
69
- messageId,
70
- reason: dislikeReason,
71
- });
67
+ telemetry.sendSearchAIFeedbackMessage([
68
+ {
69
+ object: 'feedback',
70
+ feedback: feedbackValue,
71
+ messageId,
72
+ reason: dislikeReason,
73
+ },
74
+ ]);
72
75
  }
73
76
  catch (error) {
74
77
  console.error('Error sending feedback', error);
@@ -134,14 +134,17 @@ function SearchDialog({ onClose, className, initialMode = 'search', }) {
134
134
  }
135
135
  return (react_1.default.createElement(SearchItem_1.SearchItem, { key: `${index}-${item.document.id}`, item: item, product: itemProduct, innerRef: innerRef, onClick: () => {
136
136
  addSearchHistoryItem(query);
137
- telemetry.sendSearchResultClickedMessage({
138
- query,
139
- url: item.document.url,
140
- totalResults: results.length.toString(),
141
- index: index.toString(),
142
- searchEngine: mode,
143
- searchSessionId,
144
- });
137
+ telemetry.sendSearchResultClickedMessage([
138
+ {
139
+ object: 'search',
140
+ query: query,
141
+ url: item.document.url,
142
+ totalResults: results.length.toString(),
143
+ index: index.toString(),
144
+ searchEngine: mode,
145
+ searchSessionId,
146
+ },
147
+ ]);
145
148
  onClose();
146
149
  } }));
147
150
  }, [onClose, product, products, addSearchHistoryItem, query, telemetry, mode, searchSessionId]);
@@ -189,9 +192,12 @@ function SearchDialog({ onClose, className, initialMode = 'search', }) {
189
192
  if (query.trim()) {
190
193
  aiSearch.askQuestion(query);
191
194
  }
192
- telemetry.sendSearchAiOpenedMessage({
193
- method: 'ai_search_button',
194
- });
195
+ telemetry.sendSearchAiOpenedMessage([
196
+ {
197
+ object: 'search',
198
+ method: 'ai_search_button',
199
+ },
200
+ ]);
195
201
  } }, translate('search.ai.button', 'Search with AI'))) : null,
196
202
  showSearchFilterButton && (react_1.default.createElement(SearchFilterToggleButton, { icon: react_1.default.createElement(SettingsIcon_1.SettingsIcon, null), onClick: onFilterToggle })))))) : (react_1.default.createElement(AiDialogHeaderWrapper, null,
197
203
  initialMode === 'ai-dialog' ? (react_1.default.createElement(AiDialogHeaderTitle, null,
@@ -219,18 +225,24 @@ function SearchDialog({ onClose, className, initialMode = 'search', }) {
219
225
  if (query.trim()) {
220
226
  aiSearch.askQuestion(query);
221
227
  }
222
- telemetry.sendSearchAiOpenedMessage({
223
- method: 'ai_search_input',
224
- });
228
+ telemetry.sendSearchAiOpenedMessage([
229
+ {
230
+ object: 'search',
231
+ method: 'ai_search_input',
232
+ },
233
+ ]);
225
234
  }, onKeyDown: (e) => {
226
235
  if (e.key === 'Enter') {
227
236
  setMode('ai-dialog');
228
237
  if (query.trim()) {
229
238
  aiSearch.askQuestion(query);
230
239
  }
231
- telemetry.sendSearchAiOpenedMessage({
232
- method: 'ai_search_input',
233
- });
240
+ telemetry.sendSearchAiOpenedMessage([
241
+ {
242
+ object: 'search',
243
+ method: 'ai_search_input',
244
+ },
245
+ ]);
234
246
  }
235
247
  }, ref: aiQueryRef, tabIndex: 0, role: "option", "aria-selected": "true" },
236
248
  react_1.default.createElement(AiStarsIcon_1.AiStarsIcon, { style: { flexShrink: 0 }, color: "var(--search-ai-icon-color)", size: "36px", background: "var(--search-ai-icon-bg-color)", margin: "0 var(--spacing-md) 0 0", borderRadius: "var(--border-radius-lg)" }),
@@ -264,11 +276,14 @@ function SearchDialog({ onClose, className, initialMode = 'search', }) {
264
276
  translate('search.loading', 'Loading...'))) : (react_1.default.createElement(SearchMessage, { "data-translation-key": "search.noResults" },
265
277
  react_1.default.createElement("b", null, translate('search.noResults.title', 'No results'))))) : (react_1.default.createElement(react_1.default.Fragment, null,
266
278
  react_1.default.createElement(SearchRecent_1.SearchRecent, { onSelect: (query, index) => {
267
- telemetry.sendSearchRecentClickedMessage({
268
- query,
269
- index: index.toString(),
270
- searchSessionId,
271
- });
279
+ telemetry.sendSearchRecentClickedMessage([
280
+ {
281
+ object: 'search',
282
+ query,
283
+ index: index.toString(),
284
+ searchSessionId,
285
+ },
286
+ ]);
272
287
  setQuery(query);
273
288
  focusSearchInput();
274
289
  } }),
@@ -24,7 +24,7 @@ function useSearchDialog() {
24
24
  if (hotKeys) {
25
25
  (0, hotkeys_js_1.default)(hotKeys, (ev) => {
26
26
  setIsOpen(true);
27
- telemetry.sendSearchOpenedMessage({ method: 'shortcut' });
27
+ telemetry.sendSearchOpenedMessage([{ object: 'search', method: 'shortcut' }]);
28
28
  ev.preventDefault();
29
29
  });
30
30
  return () => hotkeys_js_1.default.unbind(hotKeys);
@@ -32,7 +32,7 @@ function useSearchDialog() {
32
32
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
33
  }, [hotKeys]);
34
34
  const onOpen = (0, react_1.useCallback)(function () {
35
- telemetry.sendSearchOpenedMessage({ method: 'click' });
35
+ telemetry.sendSearchOpenedMessage([{ object: 'search', method: 'click' }]);
36
36
  setIsOpen(true);
37
37
  // eslint-disable-next-line react-hooks/exhaustive-deps
38
38
  }, []);
@@ -35,7 +35,9 @@ const useColorSwitcher = () => {
35
35
  window.requestAnimationFrame(() => {
36
36
  root.classList.remove('notransition');
37
37
  });
38
- telemetry.sendColorModeSwitchedMessage({ from: activeColorMode, to: newMode });
38
+ telemetry.sendColorModeSwitchedMessage([
39
+ { object: 'color_mode', from: activeColorMode, to: newMode },
40
+ ]);
39
41
  setActiveColorMode(newMode);
40
42
  };
41
43
  /**
@@ -65,7 +65,9 @@ function usePageActions(pageSlug, mcpUrl, actions) {
65
65
  mcpConfig: config,
66
66
  translate,
67
67
  onClickCallback: isDocsMcp
68
- ? () => telemetry.sendPageActionsButtonClickedMessage(Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: `docs-mcp-${clientType}` }))
68
+ ? () => telemetry.sendPageActionsButtonClickedMessage([
69
+ Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: `docs-mcp-${clientType}` }),
70
+ ])
69
71
  : undefined,
70
72
  });
71
73
  }, [mcpUrl, mcpConfig, translate, telemetry, pageSlug]);
@@ -98,7 +100,9 @@ function usePageActions(pageSlug, mcpUrl, actions) {
98
100
  }
99
101
  const text = yield result.text();
100
102
  clipboard_service_1.ClipboardService.copyCustom(text);
101
- telemetry.sendPageActionsButtonClickedMessage(Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'copy' }));
103
+ telemetry.sendPageActionsButtonClickedMessage([
104
+ Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'copy' }),
105
+ ]);
102
106
  }
103
107
  catch (error) {
104
108
  console.error(error);
@@ -112,7 +116,9 @@ function usePageActions(pageSlug, mcpUrl, actions) {
112
116
  iconComponent: MarkdownFullIcon_1.MarkdownFullIcon,
113
117
  link: mdPageUrl,
114
118
  onClick: () => {
115
- telemetry.sendPageActionsButtonClickedMessage(Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'view' }));
119
+ telemetry.sendPageActionsButtonClickedMessage([
120
+ Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'view' }),
121
+ ]);
116
122
  },
117
123
  }),
118
124
  chatgpt: () => {
@@ -126,7 +132,9 @@ function usePageActions(pageSlug, mcpUrl, actions) {
126
132
  iconComponent: ChatGptIcon_1.ChatGptIcon,
127
133
  link: getExternalAiPromptLink('https://chat.openai.com', mdPageUrl),
128
134
  onClick: () => {
129
- telemetry.sendPageActionsButtonClickedMessage(Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'chatgpt' }));
135
+ telemetry.sendPageActionsButtonClickedMessage([
136
+ Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'chatgpt' }),
137
+ ]);
130
138
  },
131
139
  };
132
140
  },
@@ -141,7 +149,9 @@ function usePageActions(pageSlug, mcpUrl, actions) {
141
149
  iconComponent: ClaudeIcon_1.ClaudeIcon,
142
150
  link: getExternalAiPromptLink('https://claude.ai/new', mdPageUrl),
143
151
  onClick: () => {
144
- telemetry.sendPageActionsButtonClickedMessage(Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'claude' }));
152
+ telemetry.sendPageActionsButtonClickedMessage([
153
+ Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'claude' }),
154
+ ]);
145
155
  },
146
156
  };
147
157
  },
@@ -15,7 +15,7 @@ function useProductPicker() {
15
15
  function setProduct(product) {
16
16
  if (!product)
17
17
  return;
18
- telemetry.sendProductPickedMessage({ product: product.slug });
18
+ telemetry.sendProductPickedMessage([{ object: 'product', product: product.slug }]);
19
19
  if (typeof document === 'undefined')
20
20
  return;
21
21
  if (product.name) {
@@ -95,6 +95,7 @@ const CardWrapper = styled_components_1.default.div.attrs(({ $isCardLink, $varia
95
95
  overflow: hidden;
96
96
  transition: box-shadow 0.3s ease;
97
97
  position: relative;
98
+ text-decoration: none;
98
99
  --md-paragraph-margin: 0;
99
100
  --link-decoration-hover: none;
100
101
 
@@ -40,10 +40,31 @@ exports.Heading = Heading;
40
40
  const react_1 = __importStar(require("react"));
41
41
  const styled_components_1 = __importDefault(require("styled-components"));
42
42
  const react_router_dom_1 = require("react-router-dom");
43
+ const Image_1 = require("../../../markdoc/components/Image/Image");
43
44
  const utils_1 = require("../../../core/utils");
44
45
  const LinkIcon_1 = require("../../../icons/LinkIcon/LinkIcon");
45
46
  const PageActions_1 = require("../../../components/PageActions/PageActions");
46
47
  const hooks_1 = require("../../../core/hooks");
48
+ function renderWithSpanWrapper(children) {
49
+ const childrenArray = react_1.default.Children.toArray(children);
50
+ if (childrenArray.length === 0)
51
+ return null;
52
+ const first = childrenArray[0];
53
+ const last = childrenArray[childrenArray.length - 1];
54
+ // Check if an element is an <img> or the Markdoc Image component
55
+ const isImage = (node) => {
56
+ if (!(0, react_1.isValidElement)(node))
57
+ return false;
58
+ if (typeof node.type === 'string')
59
+ return node.type === 'img';
60
+ return node.type === Image_1.Image;
61
+ };
62
+ const middleChildren = childrenArray.slice(isImage(first) ? 1 : 0, isImage(last) ? childrenArray.length - 1 : childrenArray.length);
63
+ return (react_1.default.createElement(react_1.default.Fragment, null,
64
+ isImage(first) && first,
65
+ middleChildren.length > 0 && react_1.default.createElement(StyledHeadingText, null, middleChildren),
66
+ isImage(last) && last));
67
+ }
47
68
  /**
48
69
  * Class name for all MD tags
49
70
  */
@@ -64,12 +85,23 @@ function Heading({ level, id, children, 'data-source': dataSource, 'data-hash':
64
85
  'data-hash': dataHash,
65
86
  }, react_1.default.createElement(HeadingContentWrapper, null,
66
87
  linkEl,
67
- react_1.default.createElement("span", null, children),
88
+ react_1.default.createElement("span", null, renderWithSpanWrapper(children)),
68
89
  isMarkdownPage && __idx === 0 ? react_1.default.createElement(PageActions_1.PageActions, { pageSlug: pathname }) : null));
69
90
  }
70
91
  const HeadingContentWrapper = styled_components_1.default.div `
71
92
  display: flex;
72
93
  gap: var(--spacing-xs);
73
- align-items: center;
94
+
95
+ & > span {
96
+ display: flex;
97
+ align-items: flex-start;
98
+ gap: var(--spacing-sm);
99
+ }
100
+ `;
101
+ const StyledHeadingText = styled_components_1.default.span `
102
+ margin: auto 0;
103
+ && > img:only-child {
104
+ display: inline-block;
105
+ }
74
106
  `;
75
107
  //# sourceMappingURL=Heading.js.map