@redocly/theme 0.56.0-next.9 → 0.56.0

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 (206) hide show
  1. package/lib/components/Button/Button.d.ts +1 -1
  2. package/lib/components/Button/Button.js +2 -1
  3. package/lib/components/Button/ButtonGroup.d.ts +12 -0
  4. package/lib/components/Button/ButtonGroup.js +38 -0
  5. package/lib/components/Button/variables.js +32 -5
  6. package/lib/components/Catalog/Catalog.d.ts +1 -1
  7. package/lib/components/Catalog/CatalogCardView/CatalogCard.js +2 -2
  8. package/lib/components/Catalog/CatalogSelector.d.ts +1 -1
  9. package/lib/components/Catalog/CatalogSelector.js +4 -3
  10. package/lib/components/Catalog/CatalogViewModeToggle.d.ts +1 -1
  11. package/lib/components/CodeBlock/CodeBlock.d.ts +16 -6
  12. package/lib/components/CodeBlock/CodeBlock.js +2 -2
  13. package/lib/components/CodeBlock/CodeBlockControls.d.ts +4 -3
  14. package/lib/components/CodeBlock/CodeBlockControls.js +8 -5
  15. package/lib/components/CodeBlock/CodeBlockDropdown.d.ts +3 -0
  16. package/lib/components/CodeBlock/CodeBlockDropdown.js +35 -0
  17. package/lib/components/CodeBlock/CodeBlockTabs.d.ts +2 -2
  18. package/lib/components/CodeBlock/CodeBlockTabs.js +18 -9
  19. package/lib/components/CodeBlock/variables.js +1 -1
  20. package/lib/components/Dropdown/Dropdown.js +1 -0
  21. package/lib/components/Dropdown/DropdownMenu.js +4 -0
  22. package/lib/components/Dropdown/variables.js +1 -0
  23. package/lib/components/Footer/FooterItem.js +4 -7
  24. package/lib/components/Footer/variables.js +2 -2
  25. package/lib/components/Markdown/Markdown.js +9 -9
  26. package/lib/components/Markdown/styles/headingAnchor.js +0 -1
  27. package/lib/components/Menu/MenuItem.js +5 -5
  28. package/lib/components/Menu/variables.js +1 -1
  29. package/lib/components/Navbar/NavbarItem.js +8 -39
  30. package/lib/components/Navbar/variables.js +2 -2
  31. package/lib/components/PageActions/PageActions.d.ts +6 -0
  32. package/lib/components/PageActions/PageActions.js +104 -0
  33. package/lib/components/PageActions/PageActionsMenuItem.d.ts +7 -0
  34. package/lib/components/PageActions/PageActionsMenuItem.js +58 -0
  35. package/lib/components/PageActions/variables.d.ts +1 -0
  36. package/lib/components/PageActions/variables.dark.d.ts +1 -0
  37. package/lib/components/PageActions/variables.dark.js +9 -0
  38. package/lib/components/PageActions/variables.js +37 -0
  39. package/lib/components/TableOfContent/TableOfContent.js +15 -12
  40. package/lib/components/Tags/CounterTag.d.ts +1 -1
  41. package/lib/components/Tags/HttpTag.d.ts +1 -1
  42. package/lib/core/constants/common.d.ts +4 -0
  43. package/lib/core/constants/common.js +5 -1
  44. package/lib/core/contexts/CodeSnippetContext.d.ts +7 -0
  45. package/lib/core/contexts/CodeSnippetContext.js +23 -0
  46. package/lib/core/contexts/index.d.ts +1 -0
  47. package/lib/core/contexts/index.js +1 -0
  48. package/lib/core/hooks/__mocks__/use-theme-hooks.d.ts +1 -0
  49. package/lib/core/hooks/__mocks__/use-theme-hooks.js +1 -0
  50. package/lib/core/hooks/code-walkthrough/use-renderable-files.d.ts +1 -2
  51. package/lib/core/hooks/code-walkthrough/use-renderable-files.js +2 -2
  52. package/lib/core/hooks/index.d.ts +1 -0
  53. package/lib/core/hooks/index.js +1 -0
  54. package/lib/core/hooks/use-active-heading.d.ts +7 -2
  55. package/lib/core/hooks/use-active-heading.js +160 -23
  56. package/lib/core/hooks/use-codeblock-tabs-controls.d.ts +2 -2
  57. package/lib/core/hooks/use-codeblock-tabs-controls.js +6 -6
  58. package/lib/core/hooks/use-local-state.d.ts +1 -0
  59. package/lib/core/hooks/use-local-state.js +32 -0
  60. package/lib/core/hooks/use-page-actions.d.ts +2 -0
  61. package/lib/core/hooks/use-page-actions.js +101 -0
  62. package/lib/core/hooks/use-theme-hooks.js +2 -0
  63. package/lib/core/styles/dark.js +2 -0
  64. package/lib/core/styles/global.js +2 -0
  65. package/lib/core/types/hooks.d.ts +2 -1
  66. package/lib/core/types/index.d.ts +1 -0
  67. package/lib/core/types/index.js +1 -0
  68. package/lib/core/types/l10n.d.ts +1 -1
  69. package/lib/core/types/page-actions.d.ts +15 -0
  70. package/lib/core/types/page-actions.js +3 -0
  71. package/lib/core/types/sidebar.d.ts +1 -0
  72. package/lib/core/utils/enhanced-smoothstep.d.ts +5 -0
  73. package/lib/core/utils/enhanced-smoothstep.js +15 -0
  74. package/lib/core/utils/get-file-icon.d.ts +3 -2
  75. package/lib/core/utils/get-file-icon.js +109 -29
  76. package/lib/core/utils/icon-resolver.d.ts +28 -0
  77. package/lib/core/utils/icon-resolver.js +52 -0
  78. package/lib/core/utils/index.d.ts +4 -1
  79. package/lib/core/utils/index.js +4 -1
  80. package/lib/core/utils/lang-to-name.d.ts +1 -0
  81. package/lib/core/utils/lang-to-name.js +37 -0
  82. package/lib/core/utils/{text-transform.js → string.js} +1 -1
  83. package/lib/ext/configure.d.ts +1 -1
  84. package/lib/icons/CDNIcon/CDNIcon.d.ts +14 -0
  85. package/lib/icons/CDNIcon/CDNIcon.js +48 -0
  86. package/lib/icons/ChatGptIcon/ChatGptIcon.d.ts +9 -0
  87. package/lib/icons/ChatGptIcon/ChatGptIcon.js +22 -0
  88. package/lib/icons/CheckmarkOutlineIcon/CheckmarkOutlineIcon.d.ts +9 -0
  89. package/lib/icons/CheckmarkOutlineIcon/CheckmarkOutlineIcon.js +23 -0
  90. package/lib/icons/ClaudeIcon/ClaudeIcon.d.ts +9 -0
  91. package/lib/icons/ClaudeIcon/ClaudeIcon.js +22 -0
  92. package/lib/icons/GenericIcon/GenericIcon.d.ts +11 -0
  93. package/lib/icons/GenericIcon/GenericIcon.js +61 -0
  94. package/lib/icons/MarkdownFullIcon/MarkdownFullIcon.d.ts +9 -0
  95. package/lib/icons/MarkdownFullIcon/MarkdownFullIcon.js +23 -0
  96. package/lib/icons/NoneIcon/NoneIcon.d.ts +9 -0
  97. package/lib/icons/NoneIcon/NoneIcon.js +17 -0
  98. package/lib/icons/types.d.ts +6 -0
  99. package/lib/index.d.ts +6 -0
  100. package/lib/index.js +6 -0
  101. package/lib/layouts/CodeWalkthroughLayout.js +2 -2
  102. package/lib/layouts/DocumentationLayout.js +14 -10
  103. package/lib/markdoc/components/Cards/CardIcon.js +7 -19
  104. package/lib/markdoc/components/CodeGroup/CodeGroup.d.ts +4 -0
  105. package/lib/markdoc/components/CodeGroup/CodeGroup.js +72 -0
  106. package/lib/markdoc/components/CodeWalkthrough/CodePanelHeader.js +7 -4
  107. package/lib/markdoc/components/Heading/Heading.d.ts +2 -1
  108. package/lib/markdoc/components/Heading/Heading.js +21 -3
  109. package/lib/markdoc/components/Icon/Icon.d.ts +3 -0
  110. package/lib/markdoc/components/Icon/Icon.js +29 -0
  111. package/lib/markdoc/components/Tabs/Tab.d.ts +2 -1
  112. package/lib/markdoc/components/Tabs/Tab.js +5 -2
  113. package/lib/markdoc/components/Tabs/Tabs.d.ts +1 -1
  114. package/lib/markdoc/components/Tabs/variables.js +2 -0
  115. package/lib/markdoc/components/default.d.ts +2 -0
  116. package/lib/markdoc/components/default.js +2 -0
  117. package/lib/markdoc/default.js +4 -0
  118. package/lib/markdoc/tags/card.js +1 -1
  119. package/lib/markdoc/tags/code-group.d.ts +2 -0
  120. package/lib/markdoc/tags/code-group.js +23 -0
  121. package/lib/markdoc/tags/code-snippet.js +1 -1
  122. package/lib/markdoc/tags/icon.d.ts +2 -0
  123. package/lib/markdoc/tags/icon.js +16 -0
  124. package/lib/markdoc/tags/tab.js +1 -0
  125. package/package.json +3 -3
  126. package/src/components/Button/Button.tsx +3 -2
  127. package/src/components/Button/ButtonGroup.tsx +53 -0
  128. package/src/components/Button/variables.ts +32 -5
  129. package/src/components/Catalog/Catalog.tsx +1 -1
  130. package/src/components/Catalog/CatalogCardView/CatalogCard.tsx +1 -1
  131. package/src/components/Catalog/CatalogSelector.tsx +3 -1
  132. package/src/components/Catalog/CatalogViewModeToggle.tsx +1 -1
  133. package/src/components/CodeBlock/CodeBlock.tsx +14 -5
  134. package/src/components/CodeBlock/CodeBlockControls.tsx +14 -6
  135. package/src/components/CodeBlock/CodeBlockDropdown.tsx +53 -0
  136. package/src/components/CodeBlock/CodeBlockTabs.tsx +29 -20
  137. package/src/components/CodeBlock/variables.ts +1 -1
  138. package/src/components/Dropdown/Dropdown.tsx +1 -0
  139. package/src/components/Dropdown/DropdownMenu.tsx +4 -0
  140. package/src/components/Dropdown/variables.ts +1 -0
  141. package/src/components/Footer/FooterItem.tsx +5 -12
  142. package/src/components/Footer/variables.ts +2 -2
  143. package/src/components/Markdown/Markdown.tsx +3 -3
  144. package/src/components/Markdown/styles/headingAnchor.ts +0 -1
  145. package/src/components/Menu/MenuItem.tsx +5 -5
  146. package/src/components/Menu/variables.ts +1 -1
  147. package/src/components/Navbar/NavbarItem.tsx +8 -17
  148. package/src/components/Navbar/variables.ts +2 -2
  149. package/src/components/PageActions/PageActions.tsx +110 -0
  150. package/src/components/PageActions/PageActionsMenuItem.tsx +73 -0
  151. package/src/components/PageActions/variables.dark.ts +6 -0
  152. package/src/components/PageActions/variables.ts +34 -0
  153. package/src/components/TableOfContent/TableOfContent.tsx +33 -36
  154. package/src/core/constants/common.ts +4 -0
  155. package/src/core/contexts/CodeSnippetContext.tsx +31 -0
  156. package/src/core/contexts/index.ts +1 -0
  157. package/src/core/hooks/__mocks__/use-theme-hooks.ts +1 -0
  158. package/src/core/hooks/code-walkthrough/use-renderable-files.ts +3 -4
  159. package/src/core/hooks/index.ts +1 -0
  160. package/src/core/hooks/use-active-heading.ts +199 -28
  161. package/src/core/hooks/use-codeblock-tabs-controls.ts +8 -8
  162. package/src/core/hooks/use-local-state.ts +30 -0
  163. package/src/core/hooks/use-page-actions.ts +115 -0
  164. package/src/core/hooks/use-theme-hooks.ts +2 -0
  165. package/src/core/styles/dark.ts +2 -1
  166. package/src/core/styles/global.ts +2 -0
  167. package/src/core/types/hooks.ts +2 -0
  168. package/src/core/types/index.ts +1 -0
  169. package/src/core/types/l10n.ts +12 -0
  170. package/src/core/types/page-actions.ts +18 -0
  171. package/src/core/types/sidebar.ts +1 -0
  172. package/src/core/utils/enhanced-smoothstep.ts +14 -0
  173. package/src/core/utils/get-file-icon.tsx +94 -0
  174. package/src/core/utils/icon-resolver.ts +57 -0
  175. package/src/core/utils/index.ts +4 -1
  176. package/src/core/utils/lang-to-name.ts +35 -0
  177. package/src/ext/configure.ts +1 -1
  178. package/src/icons/CDNIcon/CDNIcon.tsx +47 -0
  179. package/src/icons/ChatGptIcon/ChatGptIcon.tsx +23 -0
  180. package/src/icons/CheckmarkOutlineIcon/CheckmarkOutlineIcon.tsx +24 -0
  181. package/src/icons/ClaudeIcon/ClaudeIcon.tsx +23 -0
  182. package/src/icons/GenericIcon/GenericIcon.tsx +69 -0
  183. package/src/icons/MarkdownFullIcon/MarkdownFullIcon.tsx +24 -0
  184. package/src/icons/NoneIcon/NoneIcon.tsx +17 -0
  185. package/src/icons/types.ts +7 -0
  186. package/src/index.ts +6 -0
  187. package/src/layouts/CodeWalkthroughLayout.tsx +1 -1
  188. package/src/layouts/DocumentationLayout.tsx +23 -13
  189. package/src/markdoc/components/Cards/CardIcon.tsx +6 -21
  190. package/src/markdoc/components/CodeGroup/CodeGroup.tsx +78 -0
  191. package/src/markdoc/components/CodeWalkthrough/CodePanelHeader.tsx +7 -4
  192. package/src/markdoc/components/Heading/Heading.tsx +22 -3
  193. package/src/markdoc/components/Icon/Icon.tsx +16 -0
  194. package/src/markdoc/components/Tabs/Tab.tsx +6 -1
  195. package/src/markdoc/components/Tabs/Tabs.tsx +1 -1
  196. package/src/markdoc/components/Tabs/variables.ts +2 -0
  197. package/src/markdoc/components/default.ts +2 -0
  198. package/src/markdoc/default.ts +4 -0
  199. package/src/markdoc/tags/card.ts +1 -1
  200. package/src/markdoc/tags/code-group.ts +21 -0
  201. package/src/markdoc/tags/code-snippet.ts +1 -1
  202. package/src/markdoc/tags/icon.ts +14 -0
  203. package/src/markdoc/tags/tab.ts +1 -0
  204. package/src/core/utils/get-file-icon.ts +0 -42
  205. /package/lib/core/utils/{text-transform.d.ts → string.d.ts} +0 -0
  206. /package/src/core/utils/{text-transform.ts → string.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import styled, { css } from 'styled-components';
2
+ import styled from 'styled-components';
3
3
  import { useLocation } from 'react-router-dom';
4
4
 
5
5
  import type { JSX } from 'react';
@@ -17,6 +17,7 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
17
17
  import { LaunchIcon } from '@redocly/theme/icons/LaunchIcon/LaunchIcon';
18
18
  import { Link } from '@redocly/theme/components/Link/Link';
19
19
  import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown';
20
+ import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
20
21
 
21
22
  export type NavbarItemProps = {
22
23
  navItem: ResolvedNavItem;
@@ -52,7 +53,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
52
53
  target={item.target}
53
54
  to={item.link}
54
55
  >
55
- <NavbarIcon url={item.icon} />
56
+ <NavbarIcon icon={item.icon} srcSet={item.srcSet} />
56
57
  <NavbarLabel data-translation-key={item.labelTranslationKey}>
57
58
  {translate(item.labelTranslationKey, item.label)}
58
59
  </NavbarLabel>
@@ -74,7 +75,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
74
75
  data-translation-key={item.labelTranslationKey}
75
76
  external={item.external}
76
77
  >
77
- <NavbarIcon url={item.icon} />
78
+ <NavbarIcon icon={item.icon} srcSet={item.srcSet} />
78
79
  <NavbarLabel data-translation-key={item.labelTranslationKey}>
79
80
  {translate(item.labelTranslationKey, item.label)}
80
81
  </NavbarLabel>
@@ -132,20 +133,10 @@ const NavbarLabel = styled.span`
132
133
  vertical-align: middle;
133
134
  `;
134
135
 
135
- const NavbarIcon = styled.i<{ url?: string }>`
136
- ${({ url }) =>
137
- url &&
138
- css`
139
- background-image: url('${url}');
140
- width: var(--navbar-item-icon-width);
141
- height: var(--navbar-item-icon-height);
142
- display: inline-block;
143
- background-size: contain;
144
- margin-right: var(--navbar-item-icon-margin-right);
145
- vertical-align: middle;
146
- background-position: center;
147
- background-repeat: no-repeat;
148
- `}
136
+ const NavbarIcon = styled(GenericIcon)`
137
+ --icon-width: var(--navbar-item-icon-width);
138
+ --icon-height: var(--navbar-item-icon-height);
139
+ margin-right: var(--navbar-item-icon-margin-right);
149
140
  `;
150
141
 
151
142
  const ExternalLinkIcon = styled(LaunchIcon)`
@@ -35,8 +35,8 @@ export const navbar = css`
35
35
  --navbar-item-bg-color-hover: var(--bg-color);
36
36
  --navbar-item-bottom-border-hover: none;
37
37
 
38
- --navbar-item-icon-width: 1.5em; // @presenter Spacing
39
- --navbar-item-icon-height: 1.5em; // @presenter Spacing
38
+ --navbar-item-icon-width: 1.25em; // @presenter Spacing
39
+ --navbar-item-icon-height: 1.25em; // @presenter Spacing
40
40
  --navbar-item-icon-margin-right: 0.5em; // @presenter Spacing
41
41
 
42
42
  --navbar-logo-height: var(--logo-height);
@@ -0,0 +1,110 @@
1
+ import React, { useState } from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { JSX } from 'react';
5
+ import type { PageAction } from '@redocly/theme/core/types';
6
+ import type { DropdownMenuItemProps } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
7
+
8
+ import { PageActionsMenuItem } from '@redocly/theme/components/PageActions/PageActionsMenuItem';
9
+ import { Link } from '@redocly/theme/components/Link/Link';
10
+ import { ButtonGroup } from '@redocly/theme/components/Button/ButtonGroup';
11
+ import { Button } from '@redocly/theme/components/Button/Button';
12
+ import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown';
13
+ import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
14
+ import { Spinner } from '@redocly/theme/icons/Spinner/Spinner';
15
+ import { CheckmarkFilledIcon } from '@redocly/theme/icons/CheckmarkFilledIcon/CheckmarkFilledIcon';
16
+ import { usePageActions } from '@redocly/theme/core/hooks';
17
+
18
+ type ActionState = 'idle' | 'processing' | 'done';
19
+
20
+ type PageActionProps = {
21
+ pageSlug: string;
22
+ };
23
+
24
+ const ACTION_DONE_DISPLAY_DURATION = 1000;
25
+
26
+ export function PageActions(props: PageActionProps): JSX.Element | null {
27
+ const { pageSlug } = props;
28
+
29
+ const actions = usePageActions(pageSlug || '/');
30
+
31
+ const [actionState, setActionState] = useState<ActionState>('idle');
32
+
33
+ if (!actions.length) {
34
+ return null;
35
+ }
36
+
37
+ const buttonAction = actions[0];
38
+
39
+ const handleActionClick = async (action: PageAction) => {
40
+ if (!('onClick' in action)) {
41
+ return;
42
+ }
43
+
44
+ setActionState('processing');
45
+
46
+ await action.onClick();
47
+ setActionState('done');
48
+ setTimeout(() => {
49
+ setActionState('idle');
50
+ }, ACTION_DONE_DISPLAY_DURATION);
51
+ };
52
+
53
+ const menuItems: DropdownMenuItemProps[] = actions.map((action) => ({
54
+ content:
55
+ 'link' in action ? (
56
+ <LinkMenuItem to={action.link} external>
57
+ <PageActionsMenuItem pageAction={action} />
58
+ </LinkMenuItem>
59
+ ) : (
60
+ <PageActionsMenuItem pageAction={action} />
61
+ ),
62
+ onAction: 'onClick' in action ? () => handleActionClick(action) : undefined,
63
+ }));
64
+
65
+ return (
66
+ <PageActionsWrapper>
67
+ <ButtonGroup variant="outlined" size="medium">
68
+ <Button
69
+ icon={renderIcon(buttonAction, actionState)}
70
+ to={'link' in buttonAction ? buttonAction.link : undefined}
71
+ external
72
+ onClick={() => handleActionClick(buttonAction)}
73
+ >
74
+ {buttonAction.buttonText}
75
+ </Button>
76
+ {actions.length > 1 ? (
77
+ <Dropdown withArrow trigger={<Button />} placement="bottom" alignment="end">
78
+ <DropdownMenu items={menuItems} />
79
+ </Dropdown>
80
+ ) : null}
81
+ </ButtonGroup>
82
+ </PageActionsWrapper>
83
+ );
84
+ }
85
+
86
+ function renderIcon(buttonAction: PageAction, actionState: ActionState) {
87
+ switch (actionState) {
88
+ case 'processing':
89
+ return <Spinner color="var(--page-actions-processing-icon-color)" />;
90
+ case 'done':
91
+ return <CheckmarkFilledIcon color="var(--page-actions-done-icon-color)" />;
92
+ default:
93
+ return <buttonAction.iconComponent />;
94
+ }
95
+ }
96
+
97
+ const PageActionsWrapper = styled.div`
98
+ margin-left: auto;
99
+ padding-left: var(--page-actions-padding-left);
100
+ --button-color: var(--page-actions-button-text-color);
101
+
102
+ .button-group-size-medium .button.button-size-medium {
103
+ --button-icon-left-padding: var(--page-actions-button-padding);
104
+ }
105
+ `;
106
+
107
+ const LinkMenuItem = styled(Link)`
108
+ text-decoration: none;
109
+ --link-decoration-hover: none;
110
+ `;
@@ -0,0 +1,73 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { PageAction } from '@redocly/theme/core/types';
5
+
6
+ import { LaunchIcon } from '@redocly/theme/icons/LaunchIcon/LaunchIcon';
7
+
8
+ type PageActionsMenuItemProps = {
9
+ pageAction: PageAction;
10
+ };
11
+
12
+ export function PageActionsMenuItem(props: PageActionsMenuItemProps) {
13
+ const { pageAction } = props;
14
+
15
+ return (
16
+ <MenuItemWrapper data-component-name="PageActions/PageActionsMenuItem">
17
+ <IconWrapper>
18
+ <pageAction.iconComponent />
19
+ </IconWrapper>
20
+ <ContentWrapper>
21
+ <Title>
22
+ {pageAction.title}
23
+ {'link' in pageAction ? (
24
+ <LaunchIcon color="var(--page-actions-menu-item-title-icon-color)" size="14px" />
25
+ ) : null}
26
+ </Title>
27
+ <Description>{pageAction.description}</Description>
28
+ </ContentWrapper>
29
+ </MenuItemWrapper>
30
+ );
31
+ }
32
+
33
+ const MenuItemWrapper = styled.div`
34
+ padding: var(--page-actions-menu-item-padding);
35
+ display: flex;
36
+ flex-direction: row;
37
+ align-items: center;
38
+ gap: var(--page-actions-menu-item-gap);
39
+ `;
40
+
41
+ const IconWrapper = styled.div`
42
+ color: var(--page-actions-menu-item-icon-color);
43
+ border: 1px solid var(--page-actions-menu-item-icon-border-color);
44
+ border-radius: var(--page-actions-menu-item-icon-border-radius);
45
+ width: var(--page-actions-menu-item-icon-wrapper-size);
46
+ height: var(--page-actions-menu-item-icon-wrapper-size);
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ `;
51
+
52
+ const ContentWrapper = styled.div`
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: var(--page-actions-menu-item-text-gap);
56
+ `;
57
+
58
+ const Title = styled.div`
59
+ font-weight: var(--page-actions-menu-item-title-font-weight);
60
+ font-size: var(--page-actions-menu-item-title-font-size);
61
+ line-height: var(--page-actions-menu-item-title-line-height);
62
+ color: var(--page-actions-menu-item-title-color);
63
+ display: flex;
64
+ align-items: center;
65
+ gap: var(--page-actions-menu-item-title-icon-gap);
66
+ `;
67
+
68
+ const Description = styled.div`
69
+ font-weight: var(--page-actions-menu-item-description-font-weight);
70
+ font-size: var(--page-actions-menu-item-description-font-size);
71
+ line-height: var(--page-actions-menu-item-description-line-height);
72
+ color: var(--page-actions-menu-item-description-color);
73
+ `;
@@ -0,0 +1,6 @@
1
+ import { css } from 'styled-components';
2
+
3
+ export const pageActionsDarkMode = css`
4
+ --page-actions-menu-item-icon-border-color: var(--color-warm-grey-5);
5
+ --page-actions-menu-item-description-color: var(--text-color-secondary);
6
+ `;
@@ -0,0 +1,34 @@
1
+ import { css } from 'styled-components';
2
+
3
+ export const pageActions = css`
4
+ /* Minimum spacing between page actions and heading text */
5
+ --page-actions-padding-left: var(--spacing-sm);
6
+
7
+ --page-actions-button-text-color: var(--text-color-secondary);
8
+ --page-actions-button-padding: 5px 14px 5px var(--spacing-sm);
9
+
10
+ --page-actions-menu-item-padding: 3px 0;
11
+ --page-actions-menu-item-gap: var(--spacing-xs);
12
+ --page-actions-menu-item-icon-color: var(--icon-color-secondary);
13
+ --page-actions-menu-item-icon-border-color: var(--color-warm-grey-3);
14
+ --page-actions-menu-item-icon-border-radius: var(--border-radius);
15
+ --page-actions-menu-item-icon-wrapper-size: 28px;
16
+
17
+ --page-actions-menu-item-text-gap: 2px;
18
+
19
+ --page-actions-menu-item-title-font-weight: var(--font-weight-regular);
20
+ --page-actions-menu-item-title-font-size: var(--font-size-base);
21
+ --page-actions-menu-item-title-line-height: var(--line-height-base);
22
+ --page-actions-menu-item-title-color: var(--text-color-secondary);
23
+
24
+ --page-actions-menu-item-title-icon-gap: var(--spacing-xxs);
25
+ --page-actions-menu-item-title-icon-color: var(--icon-color-secondary);
26
+
27
+ --page-actions-menu-item-description-font-weight: var(--font-weight-regular);
28
+ --page-actions-menu-item-description-font-size: var(--font-size-sm);
29
+ --page-actions-menu-item-description-line-height: var(--line-height-sm);
30
+ --page-actions-menu-item-description-color: var(--text-color-description);
31
+
32
+ --page-actions-processing-icon-color: var(--icon-color-interactive);
33
+ --page-actions-done-icon-color: var(--color-success-base);
34
+ `;
@@ -10,12 +10,7 @@ import {
10
10
  useThemeConfig,
11
11
  useFullHeight,
12
12
  } from '@redocly/theme/core/hooks';
13
- import {
14
- breakpoints,
15
- getDisplayedHeadingsIds,
16
- getDisplayedHeadings,
17
- getLeastDepth,
18
- } from '@redocly/theme/core/utils';
13
+ import { breakpoints, getDisplayedHeadings, getLeastDepth } from '@redocly/theme/core/utils';
19
14
 
20
15
  export type TableOfContentProps = {
21
16
  headings?: Array<MdHeading | null> | null | undefined;
@@ -35,9 +30,9 @@ export function TableOfContent(props: TableOfContentProps): JSX.Element | null {
35
30
 
36
31
  const displayedHeadings = getDisplayedHeadings(headings, toc.depth || 3);
37
32
  const leastDepth = getLeastDepth(displayedHeadings);
38
- const activeHeadingId = useActiveHeading(
33
+ const { heading: activeHeading, handleHeadingClick } = useActiveHeading(
39
34
  contentWrapper,
40
- getDisplayedHeadingsIds(displayedHeadings),
35
+ displayedHeadings,
41
36
  );
42
37
 
43
38
  if (toc?.hide) {
@@ -45,34 +40,36 @@ export function TableOfContent(props: TableOfContentProps): JSX.Element | null {
45
40
  }
46
41
 
47
42
  return (
48
- <>
49
- <TableOfContentMenu data-component-name="TableOfContent/TableOfContent" className={className}>
50
- <TableOfContentItems ref={sidebar}>
51
- {displayedHeadings.length ? (
52
- <TableOfContentHeader data-translation-key="toc.header">
53
- {translate('toc.header', toc.header || 'On this page')}
54
- </TableOfContentHeader>
55
- ) : null}
56
- {displayedHeadings.map((heading: MdHeading | null, idx: number) => {
57
- if (!heading) {
58
- return null;
59
- }
60
- const href = '#' + heading.id;
61
- return (
62
- <TableOfContentMenuItem
63
- key={href + idx}
64
- href={href}
65
- depth={heading.depth - leastDepth + 1 || 0}
66
- className={activeHeadingId === heading.id ? 'active' : ''}
67
- dangerouslySetInnerHTML={{ __html: heading.value || '' }}
68
- data-testid={`toc-${heading.value}`}
69
- onClick={() => telemetry.send({ type: 'toc_item.clicked' })}
70
- />
71
- );
72
- })}
73
- </TableOfContentItems>
74
- </TableOfContentMenu>
75
- </>
43
+ <TableOfContentMenu data-component-name="TableOfContent/TableOfContent" className={className}>
44
+ <TableOfContentItems ref={sidebar}>
45
+ {displayedHeadings.length ? (
46
+ <TableOfContentHeader data-translation-key="toc.header">
47
+ {translate('toc.header', toc.header || 'On this page')}
48
+ </TableOfContentHeader>
49
+ ) : null}
50
+ {displayedHeadings.map((heading: MdHeading | null, idx: number) => {
51
+ if (!heading) {
52
+ return null;
53
+ }
54
+ const href = '#' + heading.id;
55
+ return (
56
+ <TableOfContentMenuItem
57
+ key={href + idx}
58
+ href={href}
59
+ depth={heading.depth - leastDepth + 1 || 0}
60
+ className={activeHeading === heading.id ? 'active' : ''}
61
+ dangerouslySetInnerHTML={{ __html: heading.value || '' }}
62
+ data-testid={`toc-${heading.value}`}
63
+ onClick={(e) => {
64
+ e.preventDefault();
65
+ telemetry.send({ type: 'toc_item.clicked' });
66
+ handleHeadingClick(heading.id);
67
+ }}
68
+ />
69
+ );
70
+ })}
71
+ </TableOfContentItems>
72
+ </TableOfContentMenu>
76
73
  );
77
74
  }
78
75
 
@@ -1,6 +1,10 @@
1
1
  export { REDOCLY_TEAMS_RBAC } from '@redocly/config';
2
2
  export const DEFAULT_LOCALE_PLACEHOLDER = 'default_locale';
3
3
  export const CONTENT_ID = 'content';
4
+ export const ICONS_CDN_URL = {
5
+ 'font-awesome': 'https://cdn.redocly.com/icons/fa/7.0.0',
6
+ code: 'https://cdn.redocly.com/icons/code/5.24.0',
7
+ };
4
8
 
5
9
  export enum FEEDBACK_TYPES {
6
10
  RATING = 'rating',
@@ -0,0 +1,31 @@
1
+ import { createContext, useContext, useState } from 'react';
2
+
3
+ export type CodeSnippetContextType = {
4
+ activeSnippetName: string;
5
+ setActiveSnippetName: (name: string) => void;
6
+ };
7
+
8
+ export const CODE_GROUP_SNIPPET_NAME_KEY = 'redocly:codeGroupSnippetName';
9
+
10
+ export const CodeSnippetContext = createContext<CodeSnippetContextType | null>(null);
11
+
12
+ export function useActiveCodeSnippetName(
13
+ mode: 'tabs' | 'dropdown',
14
+ ): [string, (name: string) => void] {
15
+ const context = useContext(CodeSnippetContext);
16
+ if (!context) {
17
+ throw new Error('useCodeSnippetContext must be used within a CodeSnippetContext');
18
+ }
19
+
20
+ const [activeSnippetName, setActiveSnippetName] = useState(
21
+ mode === 'tabs' ? '' : context.activeSnippetName,
22
+ );
23
+
24
+ if (mode === 'tabs') {
25
+ // use non-synced state for tabs mode
26
+ return [activeSnippetName, setActiveSnippetName];
27
+ } else {
28
+ // use global synced state for dropdown mode
29
+ return [context.activeSnippetName, context.setActiveSnippetName];
30
+ }
31
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './ThemeDataContext';
2
2
  export * from './CodeWalkthrough/CodeWalkthroughControlsContext';
3
3
  export * from './CodeWalkthrough/CodeWalkthroughStepsContext';
4
+ export * from './CodeSnippetContext';
@@ -86,4 +86,5 @@ export const useThemeHooks = jest.fn(() => ({
86
86
  })),
87
87
  useLoadAndNavigate: jest.fn(),
88
88
  usePageProps: jest.fn().mockReturnValue({}),
89
+ usePageData: jest.fn().mockReturnValue(null),
89
90
  }));
@@ -1,14 +1,13 @@
1
1
  import { useMemo } from 'react';
2
2
 
3
3
  import type { CodeWalkthroughFile } from '@redocly/config';
4
- import type { IconProps } from '../../../icons/types';
5
4
 
6
5
  import { findClosestCommonDirectory } from '../../utils/find-closest-common-directory';
7
6
  import { getFileIconByExt } from '../../utils/get-file-icon';
8
7
  import { removeLeadingSlash } from '../../utils/urls';
9
8
 
10
9
  export type RenderableFile = CodeWalkthroughFile & {
11
- FileIcon: React.FunctionComponent<IconProps>;
10
+ fileIcon: React.JSX.Element;
12
11
  parentFolder: string;
13
12
  isNameDuplicate: boolean;
14
13
  inRootDir: boolean;
@@ -21,7 +20,7 @@ export function useRenderableFiles(files: CodeWalkthroughFile[]): RenderableFile
21
20
  const rootDir = findClosestCommonDirectory(filePaths);
22
21
 
23
22
  const renderableFiles = files.map((file) => {
24
- const FileIcon = getFileTypeIcon(file.basename);
23
+ const fileIcon = getFileTypeIcon(file.basename);
25
24
  const parentFolder = file.path.split('/').slice(-2, -1)[0];
26
25
  const isNameDuplicate = files.some(
27
26
  (_file) => file.basename === _file.basename && file.path !== _file.path,
@@ -30,7 +29,7 @@ export function useRenderableFiles(files: CodeWalkthroughFile[]): RenderableFile
30
29
 
31
30
  return {
32
31
  ...file,
33
- FileIcon,
32
+ fileIcon,
34
33
  inRootDir,
35
34
  parentFolder,
36
35
  isNameDuplicate,
@@ -40,3 +40,4 @@ export * from './catalog/useCatalogEntities';
40
40
  export * from './use-active-page-version';
41
41
  export * from './use-page-versions';
42
42
  export * from './use-user-teams';
43
+ export * from './use-page-actions';