@redocly/theme 0.54.3 → 0.55.0-next.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.
Files changed (91) hide show
  1. package/lib/components/Breadcrumbs/Breadcrumbs.js +3 -3
  2. package/lib/components/Button/Button.d.ts +0 -1
  3. package/lib/components/Buttons/EditPageButton.js +3 -3
  4. package/lib/components/CatalogClassic/CatalogClassicActions.js +3 -3
  5. package/lib/components/CatalogClassic/CatalogClassicCard.js +3 -3
  6. package/lib/components/CatalogClassic/CatalogClassicInfoBlock.js +3 -3
  7. package/lib/components/CodeBlock/CodeBlockControls.js +3 -3
  8. package/lib/components/Feedback/Feedback.js +3 -3
  9. package/lib/components/Feedback/ReportDialog.js +3 -3
  10. package/lib/components/Filter/FilterCheckboxes.js +3 -3
  11. package/lib/components/Footer/FooterItem.js +7 -4
  12. package/lib/components/LanguagePicker/LanguagePicker.js +3 -3
  13. package/lib/components/Logo/Logo.js +3 -3
  14. package/lib/components/Menu/MenuItem.js +3 -3
  15. package/lib/components/Navbar/Navbar.js +4 -4
  16. package/lib/components/Navbar/NavbarItem.js +3 -3
  17. package/lib/components/Search/SearchDialog.js +5 -5
  18. package/lib/components/Search/SearchInput.js +3 -3
  19. package/lib/components/Search/SearchRecent.js +3 -3
  20. package/lib/components/Search/SearchTrigger.js +4 -2
  21. package/lib/components/SidebarActions/SidebarActions.js +5 -5
  22. package/lib/components/TableOfContent/TableOfContent.js +3 -3
  23. package/lib/components/UserMenu/LoginButton.js +3 -3
  24. package/lib/components/UserMenu/LogoutMenuItem.js +3 -3
  25. package/lib/core/hooks/__mocks__/use-theme-hooks.d.ts +0 -3
  26. package/lib/core/hooks/__mocks__/use-theme-hooks.js +0 -3
  27. package/lib/core/hooks/index.d.ts +2 -0
  28. package/lib/core/hooks/index.js +2 -0
  29. package/lib/core/hooks/search/use-search-dialog.js +5 -5
  30. package/lib/core/hooks/use-color-switcher.js +3 -3
  31. package/lib/core/hooks/use-input-key-commands.js +2 -1
  32. package/lib/core/hooks/use-page-active-version.d.ts +1 -0
  33. package/lib/core/hooks/use-page-active-version.js +11 -0
  34. package/lib/core/hooks/use-page-versions.d.ts +7 -0
  35. package/lib/core/hooks/use-page-versions.js +15 -0
  36. package/lib/core/hooks/use-product-picker.js +3 -3
  37. package/lib/core/hooks/use-theme-hooks.js +4 -1
  38. package/lib/core/styles/dark.js +14 -3
  39. package/lib/core/styles/global.js +9 -6
  40. package/lib/core/types/hooks.d.ts +0 -5
  41. package/lib/core/types/l10n.d.ts +1 -1
  42. package/lib/core/utils/get-user-agent.d.ts +4 -0
  43. package/lib/core/utils/get-user-agent.js +15 -0
  44. package/lib/core/utils/index.d.ts +1 -0
  45. package/lib/core/utils/index.js +1 -0
  46. package/lib/markdoc/components/Tabs/TabList.d.ts +4 -1
  47. package/lib/markdoc/components/Tabs/TabList.js +36 -16
  48. package/lib/markdoc/components/Tabs/Tabs.js +7 -3
  49. package/package.json +3 -3
  50. package/src/components/Breadcrumbs/Breadcrumbs.tsx +3 -3
  51. package/src/components/Button/Button.tsx +1 -1
  52. package/src/components/Buttons/EditPageButton.tsx +3 -3
  53. package/src/components/CatalogClassic/CatalogClassicActions.tsx +3 -3
  54. package/src/components/CatalogClassic/CatalogClassicCard.tsx +3 -3
  55. package/src/components/CatalogClassic/CatalogClassicInfoBlock.tsx +3 -3
  56. package/src/components/CodeBlock/CodeBlockControls.tsx +3 -3
  57. package/src/components/Feedback/Feedback.tsx +3 -3
  58. package/src/components/Feedback/ReportDialog.tsx +3 -3
  59. package/src/components/Filter/FilterCheckboxes.tsx +3 -3
  60. package/src/components/Footer/FooterItem.tsx +12 -4
  61. package/src/components/LanguagePicker/LanguagePicker.tsx +3 -3
  62. package/src/components/Logo/Logo.tsx +3 -3
  63. package/src/components/Menu/MenuItem.tsx +3 -3
  64. package/src/components/Navbar/Navbar.tsx +4 -4
  65. package/src/components/Navbar/NavbarItem.tsx +3 -3
  66. package/src/components/Search/SearchDialog.tsx +5 -5
  67. package/src/components/Search/SearchInput.tsx +3 -3
  68. package/src/components/Search/SearchRecent.tsx +3 -3
  69. package/src/components/Search/SearchTrigger.tsx +9 -3
  70. package/src/components/SidebarActions/SidebarActions.tsx +5 -5
  71. package/src/components/TableOfContent/TableOfContent.tsx +3 -3
  72. package/src/components/UserMenu/LoginButton.tsx +3 -3
  73. package/src/components/UserMenu/LogoutMenuItem.tsx +3 -3
  74. package/src/core/hooks/__mocks__/use-theme-hooks.ts +0 -3
  75. package/src/core/hooks/index.ts +2 -0
  76. package/src/core/hooks/search/use-search-dialog.ts +5 -5
  77. package/src/core/hooks/use-color-switcher.ts +3 -3
  78. package/src/core/hooks/use-input-key-commands.ts +3 -1
  79. package/src/core/hooks/use-page-active-version.ts +9 -0
  80. package/src/core/hooks/use-page-versions.ts +20 -0
  81. package/src/core/hooks/use-product-picker.ts +3 -3
  82. package/src/core/hooks/use-theme-hooks.ts +4 -1
  83. package/src/core/styles/dark.ts +15 -3
  84. package/src/core/styles/global.ts +9 -6
  85. package/src/core/types/hooks.ts +1 -4
  86. package/src/core/types/l10n.ts +1 -1
  87. package/src/core/utils/get-user-agent.ts +13 -0
  88. package/src/core/utils/index.ts +1 -0
  89. package/src/markdoc/components/Tabs/TabList.tsx +69 -38
  90. package/src/markdoc/components/Tabs/Tabs.tsx +7 -3
  91. package/src/settings.yaml +1 -0
@@ -20,8 +20,8 @@ export type LanguagePickerProps = {
20
20
 
21
21
  export function LanguagePicker(props: LanguagePickerProps): JSX.Element | null {
22
22
  const { currentLocale, locales, setLocale } = useLanguagePicker();
23
- const { useOtelTelemetry } = useThemeHooks();
24
- const otelTelemetry = useOtelTelemetry();
23
+ const { useTelemetry } = useThemeHooks();
24
+ const telemetry = useTelemetry();
25
25
 
26
26
  if (locales.length < 2 || !currentLocale) {
27
27
  return null;
@@ -40,7 +40,7 @@ export function LanguagePicker(props: LanguagePickerProps): JSX.Element | null {
40
40
  onAction: () => {
41
41
  setLocale(locale.code);
42
42
  props.onChangeLanguage(locale.code);
43
- otelTelemetry.send({
43
+ telemetry.send({
44
44
  type: 'language_picker_locale.changed',
45
45
  payload: { locale: locale.code },
46
46
  });
@@ -14,8 +14,8 @@ export type LogoProps = {
14
14
  };
15
15
 
16
16
  export function Logo({ config, className, ...otherProps }: LogoProps): JSX.Element | null {
17
- const { useOtelTelemetry } = useThemeHooks();
18
- const otelTelemetry = useOtelTelemetry();
17
+ const { useTelemetry } = useThemeHooks();
18
+ const telemetry = useTelemetry();
19
19
 
20
20
  if (!config?.image && !config?.srcSet) {
21
21
  return null;
@@ -27,7 +27,7 @@ export function Logo({ config, className, ...otherProps }: LogoProps): JSX.Eleme
27
27
  return (
28
28
  <LogoWrapper data-component-name="Logo/Logo" className={className} {...otherProps}>
29
29
  {config.link ? (
30
- <Link to={config.link} onClick={() => otelTelemetry.send({ type: 'logo.clicked' })}>
30
+ <Link to={config.link} onClick={() => telemetry.send({ type: 'logo.clicked' })}>
31
31
  {image}
32
32
  </Link>
33
33
  ) : (
@@ -17,7 +17,7 @@ import { Badge } from '@redocly/theme/components/Badge/Badge';
17
17
 
18
18
  export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Element {
19
19
  const { item, depth, className, onClick } = props;
20
- const { useTranslate, useOtelTelemetry } = useThemeHooks();
20
+ const { useTranslate, useTelemetry } = useThemeHooks();
21
21
  const { translate } = useTranslate();
22
22
  const type = getMenuItemType(item);
23
23
  const nestedMenuRef = useRef<HTMLDivElement>(null);
@@ -28,7 +28,7 @@ export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Ele
28
28
  labelRef,
29
29
  nestedMenuRef,
30
30
  });
31
- const otelTelemetry = useOtelTelemetry();
31
+ const telemetry = useTelemetry();
32
32
  const isDrilldown = type === MenuItemType.DrillDown;
33
33
  const isSeparator = type === MenuItemType.Separator;
34
34
  const isNested = type === MenuItemType.Group;
@@ -36,7 +36,7 @@ export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Ele
36
36
  const hasHttpTag = !!item.httpVerb || type === MenuItemType.Operation;
37
37
 
38
38
  const handleOnClick = () => {
39
- otelTelemetry.send({
39
+ telemetry.send({
40
40
  type: 'sidebar.item_clicked',
41
41
  payload: {
42
42
  label: item.label,
@@ -25,9 +25,9 @@ export type NavbarProps = {
25
25
  export function Navbar({ className }: NavbarProps): JSX.Element | null {
26
26
  const { isOpen, closeMobileMenu, openMobileMenu } = useMobileMenu(false);
27
27
  const themeConfig = useThemeConfig();
28
- const { useL10n, useOtelTelemetry } = useThemeHooks();
28
+ const { useL10n, useTelemetry } = useThemeHooks();
29
29
  const { changeLanguage } = useL10n();
30
- const otelTelemetry = useOtelTelemetry();
30
+ const telemetry = useTelemetry();
31
31
 
32
32
  const menu = themeConfig.navbar?.items;
33
33
 
@@ -58,11 +58,11 @@ export function Navbar({ className }: NavbarProps): JSX.Element | null {
58
58
  isOpen
59
59
  ? () => {
60
60
  closeMobileMenu();
61
- otelTelemetry.send({ type: 'mobile_menu_button_close.clicked' });
61
+ telemetry.send({ type: 'mobile_menu_button_close.clicked' });
62
62
  }
63
63
  : () => {
64
64
  openMobileMenu();
65
- otelTelemetry.send({ type: 'mobile_menu_button_open.clicked' });
65
+ telemetry.send({ type: 'mobile_menu_button_open.clicked' });
66
66
  }
67
67
  }
68
68
  icon={isOpen ? <CloseIcon /> : <MenuIcon />}
@@ -25,10 +25,10 @@ export type NavbarItemProps = {
25
25
 
26
26
  export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element | null {
27
27
  const { pathname } = useLocation();
28
- const { useTranslate, useL10nConfig, useOtelTelemetry } = useThemeHooks();
28
+ const { useTranslate, useL10nConfig, useTelemetry } = useThemeHooks();
29
29
  const { translate } = useTranslate();
30
30
  const { defaultLocale, currentLocale, locales } = useL10nConfig();
31
- const otelTelemetry = useOtelTelemetry();
31
+ const telemetry = useTelemetry();
32
32
 
33
33
  if (navItem.type !== 'link' && !navItem.items) return null;
34
34
 
@@ -46,7 +46,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
46
46
  active={isActive}
47
47
  className={className}
48
48
  onClick={() =>
49
- otelTelemetry.send({ type: 'navbar.menu_item_clicked', payload: { type: item.type } })
49
+ telemetry.send({ type: 'navbar.menu_item_clicked', payload: { type: item.type } })
50
50
  }
51
51
  external={item.external}
52
52
  target={item.target}
@@ -37,9 +37,9 @@ export type SearchDialogProps = {
37
37
  };
38
38
 
39
39
  export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Element {
40
- const { useTranslate, useCurrentProduct, useSearch, useProducts, useAiSearch, useOtelTelemetry } =
40
+ const { useTranslate, useCurrentProduct, useSearch, useProducts, useAiSearch, useTelemetry } =
41
41
  useThemeHooks();
42
- const otelTelemetry = useOtelTelemetry();
42
+ const telemetry = useTelemetry();
43
43
  const products = useProducts();
44
44
  const currentProduct = useCurrentProduct();
45
45
  const [product, setProduct] = useState(currentProduct);
@@ -139,7 +139,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
139
139
  innerRef={innerRef}
140
140
  onClick={() => {
141
141
  addSearchHistoryItem(query);
142
- otelTelemetry.send({
142
+ telemetry.send({
143
143
  type: 'search.result.clicked',
144
144
  payload: {
145
145
  query,
@@ -154,7 +154,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
154
154
  />
155
155
  );
156
156
  },
157
- [onClose, product, products, addSearchHistoryItem, query, otelTelemetry, mode],
157
+ [onClose, product, products, addSearchHistoryItem, query, telemetry, mode],
158
158
  );
159
159
 
160
160
  const showLoadMore = useCallback(
@@ -381,7 +381,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
381
381
  <>
382
382
  <SearchRecent
383
383
  onSelect={(query, index) => {
384
- otelTelemetry.send({
384
+ telemetry.send({
385
385
  type: 'search.recent.clicked',
386
386
  payload: {
387
387
  query,
@@ -33,9 +33,9 @@ export function SearchInput({
33
33
  onSubmit,
34
34
  className,
35
35
  }: SearchInputProps): JSX.Element {
36
- const { useOtelTelemetry } = useThemeHooks();
36
+ const { useTelemetry } = useThemeHooks();
37
37
  const { addSearchHistoryItem } = useRecentSearches();
38
- const otelTelemetry = useOtelTelemetry();
38
+ const telemetry = useTelemetry();
39
39
 
40
40
  const { onKeyDown } = useInputKeyCommands({
41
41
  onEnter: (event) => onSubmit?.(event),
@@ -51,7 +51,7 @@ export function SearchInput({
51
51
  const handleOnReset = () => {
52
52
  onChange('');
53
53
  addSearchHistoryItem(value);
54
- otelTelemetry.send({ type: 'search_input_reset_button.clicked' });
54
+ telemetry.send({ type: 'search_input_reset_button.clicked' });
55
55
  };
56
56
 
57
57
  return (
@@ -16,16 +16,16 @@ export type SearchRecentProps = {
16
16
 
17
17
  export function SearchRecent({ onSelect, className }: SearchRecentProps): JSX.Element | null {
18
18
  const { items, removeSearchHistoryItem } = useRecentSearches();
19
- const { useTranslate, useOtelTelemetry } = useThemeHooks();
19
+ const { useTranslate, useTelemetry } = useThemeHooks();
20
20
  const { translate } = useTranslate();
21
- const otelTelemetry = useOtelTelemetry();
21
+ const telemetry = useTelemetry();
22
22
 
23
23
  if (!items || !items.length) return null;
24
24
 
25
25
  const handleOnRemove = (e: React.MouseEvent<SVGSVGElement, MouseEvent>, item: string) => {
26
26
  e.stopPropagation();
27
27
  removeSearchHistoryItem(item);
28
- otelTelemetry.send({ type: 'search_recent_remove_button.clicked' });
28
+ telemetry.send({ type: 'search_recent_remove_button.clicked' });
29
29
  };
30
30
 
31
31
  const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>, item: string, index: number) => {
@@ -6,7 +6,7 @@ import type { JSX } from 'react';
6
6
  import { useThemeConfig, useThemeHooks } from '@redocly/theme/core/hooks';
7
7
  import { Button } from '@redocly/theme/components/Button/Button';
8
8
  import { SearchIcon } from '@redocly/theme/icons/SearchIcon/SearchIcon';
9
- import { breakpoints } from '@redocly/theme/core/utils';
9
+ import { breakpoints, getUserAgent } from '@redocly/theme/core/utils';
10
10
 
11
11
  export type SearchTriggerProps = {
12
12
  onClick: () => void;
@@ -18,7 +18,8 @@ export function SearchTrigger({ onClick, className }: SearchTriggerProps): JSX.E
18
18
  const { useTranslate } = useThemeHooks();
19
19
  const { translate } = useTranslate();
20
20
 
21
- const keyShortcuts = themeSettings?.search?.shortcuts ?? ['/'];
21
+ const defaultKeyShortcut = '⌘+K,CTRL+K';
22
+ const keyShortcuts = themeSettings?.search?.shortcuts ?? [defaultKeyShortcut];
22
23
  let mainShortcutKey: string | null | undefined = null;
23
24
 
24
25
  if (keyShortcuts) {
@@ -30,6 +31,7 @@ export function SearchTrigger({ onClick, className }: SearchTriggerProps): JSX.E
30
31
  }
31
32
 
32
33
  mainShortcutKey = mainShortcutKey?.toUpperCase();
34
+ const isMac = getUserAgent().includes('Mac');
33
35
 
34
36
  return (
35
37
  <SearchTriggerWrapper
@@ -49,7 +51,11 @@ export function SearchTrigger({ onClick, className }: SearchTriggerProps): JSX.E
49
51
  >
50
52
  <SearchIcon />
51
53
  {translate('search.navbar.label', 'Search')}
52
- {mainShortcutKey && <span>{mainShortcutKey}</span>}
54
+ {mainShortcutKey === defaultKeyShortcut ? (
55
+ <span>{isMac ? '⌘K' : 'Ctrl+K'}</span>
56
+ ) : (
57
+ <span>{mainShortcutKey}</span>
58
+ )}
53
59
  </SearchTriggerInput>
54
60
  </SearchTriggerWrapper>
55
61
  );
@@ -34,9 +34,9 @@ export const SidebarActions = ({
34
34
  requestAccessButton,
35
35
  className,
36
36
  }: SidebarActionsProps) => {
37
- const { useOtelTelemetry, useTranslate } = useThemeHooks();
37
+ const { useTelemetry, useTranslate } = useThemeHooks();
38
38
  const { translate } = useTranslate();
39
- const otelTelemetry = useOtelTelemetry();
39
+ const telemetry = useTelemetry();
40
40
  return (
41
41
  <ControlsWrap
42
42
  className={className}
@@ -48,9 +48,9 @@ export const SidebarActions = ({
48
48
  onClick={() => {
49
49
  onChangeCollapseSidebarClick();
50
50
  if (collapsedSidebar) {
51
- otelTelemetry.send({ type: 'sidebar.item_expanded' });
51
+ telemetry.send({ type: 'sidebar.item_expanded' });
52
52
  } else {
53
- otelTelemetry.send({ type: 'sidebar.item_collapsed' });
53
+ telemetry.send({ type: 'sidebar.item_collapsed' });
54
54
  }
55
55
  }}
56
56
  title={
@@ -70,7 +70,7 @@ export const SidebarActions = ({
70
70
  layout={layout}
71
71
  onClick={() => {
72
72
  onChangeViewClick();
73
- otelTelemetry.send({ type: 'change_layout_button.clicked' });
73
+ telemetry.send({ type: 'change_layout_button.clicked' });
74
74
  }}
75
75
  />
76
76
  </ControlsWrapChangeLayoutButtons>
@@ -25,9 +25,9 @@ export type TableOfContentProps = {
25
25
 
26
26
  export function TableOfContent(props: TableOfContentProps): JSX.Element | null {
27
27
  const { headings, contentWrapper, className } = props;
28
- const { useTranslate, useOtelTelemetry } = useThemeHooks();
28
+ const { useTranslate, useTelemetry } = useThemeHooks();
29
29
  const { translate } = useTranslate();
30
- const otelTelemetry = useOtelTelemetry();
30
+ const telemetry = useTelemetry();
31
31
 
32
32
  const sidebar = React.useRef<HTMLDivElement | null>(null);
33
33
  useFullHeight(sidebar);
@@ -66,7 +66,7 @@ export function TableOfContent(props: TableOfContentProps): JSX.Element | null {
66
66
  className={activeHeadingId === heading.id ? 'active' : ''}
67
67
  dangerouslySetInnerHTML={{ __html: heading.value || '' }}
68
68
  data-testid={`toc-${heading.value}`}
69
- onClick={() => otelTelemetry.send({ type: 'toc_item.clicked' })}
69
+ onClick={() => telemetry.send({ type: 'toc_item.clicked' })}
70
70
  />
71
71
  );
72
72
  })}
@@ -11,16 +11,16 @@ export type LoginButtonProps = {
11
11
  };
12
12
 
13
13
  export function LoginButton({ href, className }: LoginButtonProps): JSX.Element {
14
- const { useTranslate, useOtelTelemetry } = useThemeHooks();
14
+ const { useTranslate, useTelemetry } = useThemeHooks();
15
15
  const { translate } = useTranslate();
16
- const otelTelemetry = useOtelTelemetry();
16
+ const telemetry = useTelemetry();
17
17
 
18
18
  return (
19
19
  <div data-component-name="UserMenu/LoginButton" className={className}>
20
20
  <Button
21
21
  data-translation-key="userMenu.login"
22
22
  to={href}
23
- onClick={() => otelTelemetry.send({ type: 'login_button.clicked' })}
23
+ onClick={() => telemetry.send({ type: 'login_button.clicked' })}
24
24
  data-testid="login-btn"
25
25
  extraClass={className}
26
26
  variant="primary"
@@ -12,13 +12,13 @@ export type LogoutMenuItemProps = {
12
12
  };
13
13
 
14
14
  export function LogoutMenuItem({ iconOnly, className }: LogoutMenuItemProps): JSX.Element {
15
- const { useTranslate, useOtelTelemetry, useUserMenu } = useThemeHooks();
15
+ const { useTranslate, useTelemetry, useUserMenu } = useThemeHooks();
16
16
  const { handleLogout } = useUserMenu();
17
- const otelTelemetry = useOtelTelemetry();
17
+ const telemetry = useTelemetry();
18
18
  const { translate } = useTranslate();
19
19
 
20
20
  const handleClick = () => {
21
- otelTelemetry.send({ type: 'logout_menu_item.clicked' });
21
+ telemetry.send({ type: 'logout_menu_item.clicked' });
22
22
  handleLogout();
23
23
  };
24
24
 
@@ -11,9 +11,6 @@ export const useThemeHooks = jest.fn(() => ({
11
11
  useTelemetry: jest.fn(() => ({
12
12
  send: jest.fn(),
13
13
  })),
14
- useOtelTelemetry: jest.fn(() => ({
15
- send: jest.fn(),
16
- })),
17
14
  useBreadcrumbs: jest.fn().mockReturnValue([]),
18
15
  usePageSharedData: jest.fn().mockReturnValue({}),
19
16
  useCatalogClassic: jest.fn(() => ({
@@ -36,3 +36,5 @@ export * from '@redocly/theme/core/hooks/code-walkthrough/use-renderable-files';
36
36
  export * from '@redocly/theme/core/hooks/use-element-size';
37
37
  export * from '@redocly/theme/core/hooks/use-time-ago';
38
38
  export * from '@redocly/theme/core/hooks/use-input-key-commands';
39
+ export * from '@redocly/theme/core/hooks/use-page-active-version';
40
+ export * from '@redocly/theme/core/hooks/use-page-versions';
@@ -8,16 +8,16 @@ export function useSearchDialog() {
8
8
  const [isOpen, setIsOpen] = useState(false);
9
9
  const themeSettings = useThemeConfig();
10
10
  const location = useLocation();
11
- const { useOtelTelemetry } = useThemeHooks();
12
- const otelTelemetry = useOtelTelemetry();
13
- const keyShortcuts = themeSettings?.search?.shortcuts ?? ['/'];
11
+ const { useTelemetry } = useThemeHooks();
12
+ const telemetry = useTelemetry();
13
+ const keyShortcuts = themeSettings?.search?.shortcuts ?? ['⌘+K,CTRL+K'];
14
14
  const hotKeys = keyShortcuts?.join(',');
15
15
 
16
16
  useEffect(() => {
17
17
  if (hotKeys) {
18
18
  hotkeys(hotKeys, (ev) => {
19
19
  setIsOpen(true);
20
- otelTelemetry.send({ type: 'search.opened', payload: { method: 'shortcut' } });
20
+ telemetry.send({ type: 'search.opened', payload: { method: 'shortcut' } });
21
21
  ev.preventDefault();
22
22
  });
23
23
 
@@ -27,7 +27,7 @@ export function useSearchDialog() {
27
27
  }, [hotKeys]);
28
28
 
29
29
  const onOpen = useCallback(function () {
30
- otelTelemetry.send({ type: 'search.opened', payload: { method: 'click' } });
30
+ telemetry.send({ type: 'search.opened', payload: { method: 'click' } });
31
31
  setIsOpen(true);
32
32
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
33
  }, []);
@@ -4,8 +4,8 @@ import { useThemeConfig, useThemeHooks } from '@redocly/theme/core/hooks';
4
4
 
5
5
  export const useColorSwitcher = () => {
6
6
  const themeSettings = useThemeConfig();
7
- const { useOtelTelemetry } = useThemeHooks();
8
- const otelTelemetry = useOtelTelemetry();
7
+ const { useTelemetry } = useThemeHooks();
8
+ const telemetry = useTelemetry();
9
9
  const colorMode = themeSettings.colorMode;
10
10
  const modes = colorMode?.modes || ['light', 'dark'];
11
11
  const defaultColor = modes[0] || 'light';
@@ -33,7 +33,7 @@ export const useColorSwitcher = () => {
33
33
  window.requestAnimationFrame(() => {
34
34
  document.documentElement.classList.remove('notransition');
35
35
  });
36
- otelTelemetry.send({
36
+ telemetry.send({
37
37
  type: 'color_mode.switched',
38
38
  payload: { from: activeColorMode, to: newMode },
39
39
  });
@@ -1,5 +1,7 @@
1
1
  import { useCallback, useMemo } from 'react';
2
2
 
3
+ import { getUserAgent } from '@redocly/theme/core/utils';
4
+
3
5
  type Action = 'selectAll' | 'escape' | 'clear' | 'enter' | 'paste';
4
6
  type ActionHandlers = {
5
7
  [key in `on${Capitalize<Action>}`]?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
@@ -11,7 +13,7 @@ type KeyboardCommand = {
11
13
 
12
14
  export function useInputKeyCommands(actionHandlers?: ActionHandlers) {
13
15
  // MacOS uses Command key instead of Ctrl
14
- const ctrlKey = useMemo(() => (navigator.userAgent.includes('Mac') ? 'metaKey' : 'ctrlKey'), []);
16
+ const ctrlKey = useMemo(() => (getUserAgent().includes('Mac') ? 'metaKey' : 'ctrlKey'), []);
15
17
 
16
18
  const isSelectAll = useCallback(
17
19
  (event: React.KeyboardEvent<HTMLInputElement>) => {
@@ -0,0 +1,9 @@
1
+ import { useThemeHooks } from '@redocly/theme/core/hooks';
2
+
3
+ export function usePageActiveVersion(): string | undefined {
4
+ const { usePageVersions } = useThemeHooks();
5
+ const { versions } = usePageVersions();
6
+ const activeVersion = versions.find((version) => version.active);
7
+
8
+ return activeVersion?.version;
9
+ }
@@ -0,0 +1,20 @@
1
+ import { useThemeHooks } from '@redocly/theme/core/hooks';
2
+
3
+ export type PageVersion = {
4
+ active: boolean;
5
+ default: boolean;
6
+ label: string;
7
+ version: string;
8
+ };
9
+
10
+ export function usePageVersions(): PageVersion[] {
11
+ const { usePageVersions } = useThemeHooks();
12
+ const pageVersions = usePageVersions();
13
+
14
+ return pageVersions.versions.map((version) => ({
15
+ active: version.active,
16
+ default: version.default,
17
+ label: version.label,
18
+ version: version.version,
19
+ }));
20
+ }
@@ -3,15 +3,15 @@ import { useNavigate } from 'react-router-dom';
3
3
  import { useThemeHooks } from '@redocly/theme/core/hooks';
4
4
 
5
5
  export function useProductPicker() {
6
- const { useCurrentProduct, useProducts, useOtelTelemetry, useLoadAndNavigate } = useThemeHooks();
6
+ const { useCurrentProduct, useProducts, useTelemetry, useLoadAndNavigate } = useThemeHooks();
7
7
  const currentProduct = useCurrentProduct();
8
8
  const products = useProducts();
9
- const otelTelemetry = useOtelTelemetry();
9
+ const telemetry = useTelemetry();
10
10
  const navigate = useNavigate();
11
11
  const loadAndNavigate = useLoadAndNavigate();
12
12
  function setProduct(product: typeof currentProduct) {
13
13
  if (!product) return;
14
- otelTelemetry.send({ type: 'product.picked', payload: { product: product.slug } });
14
+ telemetry.send({ type: 'product.picked', payload: { product: product.slug } });
15
15
  loadAndNavigate({ navigate, to: product.link });
16
16
  }
17
17
  return {
@@ -10,7 +10,10 @@ const fallbacks = {
10
10
  (typeof options === 'string' ? options : options?.defaultValue) || value || '',
11
11
  }),
12
12
  useSubmitFeedback: () => ({ submitFeedback: () => {} }),
13
- useTelemetry: () => ({ telemetry: () => {} }),
13
+ useTelemetry: () => ({ send: () => {} }),
14
+ /**
15
+ * @deprecated use `useTelemetry` instead
16
+ **/
14
17
  useOtelTelemetry: () => ({ send: () => {} }),
15
18
  useBreadcrumbs: () => [],
16
19
  useCodeHighlight: () => ({ highlight: (rawContent: string) => rawContent }),
@@ -11,15 +11,27 @@ import { statusCodeDarkMode } from '@redocly/theme/components/StatusCode/variabl
11
11
  import { switcherDarkMode } from '@redocly/theme/components/Switch/variables.dark';
12
12
  import { cardsDarkMode } from '@redocly/theme/markdoc/components/Cards/variables.dark';
13
13
 
14
+
14
15
  const replayDarkMode = css`
15
16
  /**
16
17
  * @tokens Replay Colors
17
18
  * @presenter Color
18
19
  */
19
20
 
20
- --replay-undefined-variable-bg-color: rgba(249, 49, 109, 0.18); // @presenter Color
21
- --replay-defined-variable-bg-color: rgba(31, 124, 255, 0.18); // @presenter Color
22
- --replay-server-variable-bg-color: rgba(119, 45, 240, 0.2); // @presenter Color
21
+ --replay-undefined-variable-color: rgb(255, 138, 162); // @presenter Color
22
+ --replay-defined-variable-color: rgb(110, 171, 250); // @presenter Color
23
+ --replay-server-variable-color: rgb(179, 166, 249); // @presenter Color
24
+ --replay-path-parameter-color: rgb(8, 199, 224); // @presenter Color
25
+
26
+ --replay-undefined-variable-bg-color: rgba(82, 10, 24, 0.16); // @presenter Color
27
+ --replay-defined-variable-bg-color: rgba(12, 76, 158, 0.16); // @presenter Color
28
+ --replay-server-variable-bg-color: rgba(31, 10, 144, 0.16); // @presenter Color
29
+ --replay-path-parameter-bg-color: rgba(5, 88, 99, 0.16); // @presenter Color
30
+
31
+ --replay-undefined-variable-bg-color-hover: rgba(82, 10, 24, 0.4); // @presenter Color
32
+ --replay-defined-variable-bg-color-hover: rgba(12, 76, 158, 0.4); // @presenter Color
33
+ --replay-server-variable-bg-color-hover: rgba(31, 10, 144, 0.4); // @presenter Color
34
+ --replay-path-parameter-bg-color-hover: rgba(5, 88, 99, 0.4); // @presenter Color
23
35
 
24
36
  // @tokens End
25
37
  `;
@@ -1182,17 +1182,20 @@ const replay = css`
1182
1182
  * @presenter Color
1183
1183
  */
1184
1184
 
1185
- --replay-undefined-variable-color: var(--color-raspberry-6); // @presenter Color
1186
- --replay-defined-variable-color: var(--color-blue-6); // @presenter Color
1187
- --replay-server-variable-color: var(--color-purple-6); // @presenter Color
1185
+ --replay-undefined-variable-color: rgb(249, 49, 109); // @presenter Color
1186
+ --replay-defined-variable-color: rgb(31, 124, 255); // @presenter Color
1187
+ --replay-server-variable-color: rgb(91, 76, 204); // @presenter Color
1188
+ --replay-path-parameter-color: rgb(4, 117, 161); // @presenter Color
1188
1189
 
1189
1190
  --replay-undefined-variable-bg-color: rgba(249, 49, 109, 0.08); // @presenter Color
1190
1191
  --replay-defined-variable-bg-color: rgba(31, 124, 255, 0.08); // @presenter Color
1191
1192
  --replay-server-variable-bg-color: rgba(119, 45, 240, 0.08); // @presenter Color
1193
+ --replay-path-parameter-bg-color: rgba(4, 117, 161, 0.08); // @presenter Color
1192
1194
 
1193
- --replay-undefined-variable-bg-color-hover: var(--color-raspberry-2); // @presenter Color
1194
- --replay-defined-variable-bg-color-hover: var(--color-blue-2); // @presenter Color
1195
- --replay-server-variable-bg-color-hover: var(--color-purple-2); // @presenter Color
1195
+ --replay-undefined-variable-bg-color-hover: rgba(249, 49, 109, 0.16); // @presenter Color
1196
+ --replay-defined-variable-bg-color-hover: rgba(31, 124, 255, 0.16); // @presenter Color
1197
+ --replay-server-variable-bg-color-hover: rgba(119, 45, 240, 0.16); // @presenter Color
1198
+ --replay-path-parameter-bg-color-hover: rgba(4, 117, 161, 0.16); // @presenter Color
1196
1199
 
1197
1200
  // @tokens End
1198
1201
  `;
@@ -119,8 +119,7 @@ export type ThemeHooks = {
119
119
  }
120
120
  | undefined;
121
121
  useCatalogClassic: (config: CatalogConfig) => FilteredCatalog;
122
- useTelemetry: () => { send(action: TelemetryEvent, data: unknown): void };
123
- useOtelTelemetry: () => {
122
+ useTelemetry: () => {
124
123
  send(data: AsyncApiRealm.Messages): void;
125
124
  };
126
125
  useUserTeams: () => string[];
@@ -145,5 +144,3 @@ export type L10nConfig = {
145
144
  defaultLocale: string;
146
145
  locales: { code: string; name: string }[];
147
146
  };
148
-
149
- type TelemetryEvent = unknown;
@@ -214,7 +214,7 @@ export type TranslationKey =
214
214
  | 'openapi.showExample'
215
215
  | 'openapi.expandAll'
216
216
  | 'openapi.collapseAll'
217
- | 'openapi.viewDetails'
217
+ | 'openapi.viewSecurityDetails'
218
218
  | 'openapi.noResponseExample'
219
219
  | 'openapi.noResponseContent'
220
220
  | 'openapi.noRequestPayload'
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Returns user agent. Handles SSR and browser.
3
+ */
4
+ export function getUserAgent() {
5
+ const ssrUserAgent = (globalThis as any)['SSR_USER_AGENT'];
6
+
7
+ if (ssrUserAgent) {
8
+ return ssrUserAgent;
9
+ }
10
+ const browserUserAgent = typeof navigator !== 'undefined' ? navigator.userAgent : '';
11
+
12
+ return browserUserAgent;
13
+ }
@@ -31,3 +31,4 @@ export * from '@redocly/theme/core/utils/get-file-icon';
31
31
  export * from '@redocly/theme/core/utils/match-code-walkthrough-conditions';
32
32
  export * from '@redocly/theme/core/utils/replace-inputs-with-value';
33
33
  export * from '@redocly/theme/core/utils/find-closest-common-directory';
34
+ export * from '@redocly/theme/core/utils/get-user-agent';