@redocly/theme 0.47.1 → 0.48.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 (117) hide show
  1. package/lib/components/Feedback/Mood.d.ts +2 -2
  2. package/lib/components/Feedback/Mood.js +20 -15
  3. package/lib/components/Feedback/Rating.d.ts +2 -2
  4. package/lib/components/Feedback/Rating.js +6 -6
  5. package/lib/components/Feedback/Scale.d.ts +2 -2
  6. package/lib/components/Feedback/Scale.js +6 -6
  7. package/lib/components/Feedback/Sentiment.d.ts +2 -2
  8. package/lib/components/Feedback/Sentiment.js +6 -6
  9. package/lib/components/Search/SearchDialog.js +17 -11
  10. package/lib/components/Search/SearchFilter.d.ts +3 -2
  11. package/lib/components/Search/SearchFilter.js +2 -2
  12. package/lib/components/Search/SearchFilterField.d.ts +3 -2
  13. package/lib/components/Search/SearchFilterField.js +2 -2
  14. package/lib/components/Search/SearchGroups.d.ts +5 -4
  15. package/lib/components/Search/SearchGroups.js +3 -3
  16. package/lib/components/Search/variables.js +4 -0
  17. package/lib/components/Segmented/Segmented.d.ts +4 -4
  18. package/lib/components/Segmented/Segmented.js +4 -7
  19. package/lib/components/Tag/Tag.d.ts +1 -0
  20. package/lib/components/Tag/Tag.js +3 -2
  21. package/lib/core/hooks/__mocks__/search/use-search-filter.d.ts +1 -1
  22. package/lib/core/hooks/__mocks__/search/use-search-filter.js +1 -1
  23. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.d.ts +1 -1
  24. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.js +10 -5
  25. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.d.ts +1 -2
  26. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.js +20 -15
  27. package/lib/core/hooks/code-walkthrough/use-code-walkthrough.d.ts +2 -7
  28. package/lib/core/hooks/code-walkthrough/use-code-walkthrough.js +10 -3
  29. package/lib/core/hooks/code-walkthrough/use-renderable-files.d.ts +9 -0
  30. package/lib/core/hooks/code-walkthrough/use-renderable-files.js +28 -0
  31. package/lib/core/hooks/index.d.ts +1 -0
  32. package/lib/core/hooks/index.js +1 -0
  33. package/lib/core/hooks/search/use-search-filter.d.ts +2 -2
  34. package/lib/core/hooks/search/use-search-filter.js +5 -5
  35. package/lib/core/types/hooks.d.ts +1 -0
  36. package/lib/core/types/l10n.d.ts +1 -1
  37. package/lib/core/types/search.d.ts +1 -2
  38. package/lib/core/utils/download-code-walkthrough.js +9 -1
  39. package/lib/core/utils/find-closest-common-directory.d.ts +6 -0
  40. package/lib/core/utils/find-closest-common-directory.js +51 -0
  41. package/lib/core/utils/get-file-icon.js +6 -0
  42. package/lib/core/utils/index.d.ts +1 -0
  43. package/lib/core/utils/index.js +1 -0
  44. package/lib/core/utils/replace-inputs-with-value.d.ts +1 -1
  45. package/lib/core/utils/replace-inputs-with-value.js +9 -10
  46. package/lib/icons/DocumentJavaIcon/DocumentJavaIcon.d.ts +9 -0
  47. package/lib/icons/DocumentJavaIcon/DocumentJavaIcon.js +22 -0
  48. package/lib/icons/DocumentJavaIcon/index.d.ts +1 -0
  49. package/lib/icons/DocumentJavaIcon/index.js +6 -0
  50. package/lib/icons/DocumentPythonIcon/DocumentPythonIcon.d.ts +9 -0
  51. package/lib/icons/DocumentPythonIcon/DocumentPythonIcon.js +23 -0
  52. package/lib/icons/DocumentPythonIcon/index.d.ts +1 -0
  53. package/lib/icons/DocumentPythonIcon/index.js +6 -0
  54. package/lib/icons/DocumentShellIcon/DocumentShellIcon.d.ts +9 -0
  55. package/lib/icons/DocumentShellIcon/DocumentShellIcon.js +22 -0
  56. package/lib/icons/DocumentShellIcon/index.d.ts +1 -0
  57. package/lib/icons/DocumentShellIcon/index.js +6 -0
  58. package/lib/icons/__tests__/IconTestUtils.d.ts +7 -0
  59. package/lib/icons/__tests__/IconTestUtils.js +33 -0
  60. package/lib/layouts/CodeWalkthroughLayout.js +4 -1
  61. package/lib/markdoc/components/CodeWalkthrough/CodeContainer.js +1 -1
  62. package/lib/markdoc/components/CodeWalkthrough/CodeFilters.js +15 -2
  63. package/lib/markdoc/components/CodeWalkthrough/CodePanel.js +1 -1
  64. package/lib/markdoc/components/CodeWalkthrough/CodePanelHeader.js +29 -23
  65. package/lib/markdoc/components/CodeWalkthrough/CodePanelPreview.js +1 -1
  66. package/lib/markdoc/components/CodeWalkthrough/CodePanelToolbar.js +1 -1
  67. package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +6 -3
  68. package/lib/markdoc/components/CodeWalkthrough/CodeToggle.js +1 -1
  69. package/lib/markdoc/components/CodeWalkthrough/CodeWalkthrough.js +1 -1
  70. package/lib/markdoc/components/CodeWalkthrough/Input.js +4 -2
  71. package/lib/markdoc/tags/code-walkthrough.js +5 -0
  72. package/package.json +3 -3
  73. package/src/components/Feedback/Mood.tsx +25 -17
  74. package/src/components/Feedback/Rating.tsx +9 -10
  75. package/src/components/Feedback/Scale.tsx +9 -10
  76. package/src/components/Feedback/Sentiment.tsx +9 -10
  77. package/src/components/Search/SearchDialog.tsx +63 -42
  78. package/src/components/Search/SearchFilter.tsx +6 -3
  79. package/src/components/Search/SearchFilterField.tsx +4 -2
  80. package/src/components/Search/SearchGroups.tsx +13 -8
  81. package/src/components/Search/variables.ts +4 -0
  82. package/src/components/Segmented/Segmented.tsx +10 -10
  83. package/src/components/Tag/Tag.tsx +1 -1
  84. package/src/core/hooks/__mocks__/search/use-search-filter.ts +1 -1
  85. package/src/core/hooks/code-walkthrough/use-code-walkthrough-controls.ts +9 -3
  86. package/src/core/hooks/code-walkthrough/use-code-walkthrough-steps.ts +30 -18
  87. package/src/core/hooks/code-walkthrough/use-code-walkthrough.ts +13 -13
  88. package/src/core/hooks/code-walkthrough/use-renderable-files.ts +51 -0
  89. package/src/core/hooks/index.ts +1 -0
  90. package/src/core/hooks/search/use-search-filter.ts +9 -5
  91. package/src/core/types/hooks.ts +1 -0
  92. package/src/core/types/l10n.ts +5 -3
  93. package/src/core/types/search.ts +1 -2
  94. package/src/core/utils/download-code-walkthrough.ts +14 -2
  95. package/src/core/utils/find-closest-common-directory.ts +51 -0
  96. package/src/core/utils/get-file-icon.ts +7 -0
  97. package/src/core/utils/index.ts +1 -0
  98. package/src/core/utils/replace-inputs-with-value.ts +12 -9
  99. package/src/icons/DocumentJavaIcon/DocumentJavaIcon.tsx +33 -0
  100. package/src/icons/DocumentJavaIcon/index.ts +1 -0
  101. package/src/icons/DocumentPythonIcon/DocumentPythonIcon.tsx +37 -0
  102. package/src/icons/DocumentPythonIcon/index.ts +1 -0
  103. package/src/icons/DocumentShellIcon/DocumentShellIcon.tsx +33 -0
  104. package/src/icons/DocumentShellIcon/index.ts +1 -0
  105. package/src/icons/__tests__/IconTestUtils.tsx +31 -0
  106. package/src/layouts/CodeWalkthroughLayout.tsx +5 -1
  107. package/src/markdoc/components/CodeWalkthrough/CodeContainer.tsx +1 -0
  108. package/src/markdoc/components/CodeWalkthrough/CodeFilters.tsx +19 -3
  109. package/src/markdoc/components/CodeWalkthrough/CodePanel.tsx +1 -1
  110. package/src/markdoc/components/CodeWalkthrough/CodePanelHeader.tsx +64 -47
  111. package/src/markdoc/components/CodeWalkthrough/CodePanelPreview.tsx +1 -1
  112. package/src/markdoc/components/CodeWalkthrough/CodePanelToolbar.tsx +1 -1
  113. package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +6 -2
  114. package/src/markdoc/components/CodeWalkthrough/CodeToggle.tsx +1 -1
  115. package/src/markdoc/components/CodeWalkthrough/CodeWalkthrough.tsx +4 -1
  116. package/src/markdoc/components/CodeWalkthrough/Input.tsx +4 -2
  117. package/src/markdoc/tags/code-walkthrough.ts +5 -0
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.testIconComponent = testIconComponent;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_2 = require("@testing-library/react");
9
+ require("@testing-library/jest-dom");
10
+ function testIconComponent(IconComponent, componentName) {
11
+ const dataName = `icons/${componentName}/${componentName}`;
12
+ return {
13
+ rendersCorrectlyWithDefaultProps: () => {
14
+ const { container } = (0, react_2.render)(react_1.default.createElement(IconComponent, null));
15
+ const svgElement = container.querySelector('svg');
16
+ expect(svgElement).toBeInTheDocument();
17
+ expect(container.firstChild).toHaveStyle('height: 16px; width: 16px;');
18
+ },
19
+ appliesCustomSizeAndColor: () => {
20
+ const { container } = (0, react_2.render)(react_1.default.createElement(IconComponent, { size: "24px", color: "--color-primary" }));
21
+ const svgElement = container.querySelector('svg');
22
+ expect(svgElement).toBeInTheDocument();
23
+ expect(container.firstChild).toHaveStyle('height: 24px; width: 24px;');
24
+ const pathElement = container.querySelector('path');
25
+ expect(pathElement).toHaveStyle('fill: var(--color-primary);');
26
+ },
27
+ hasCorrectDataComponentName: () => {
28
+ const { container } = (0, react_2.render)(react_1.default.createElement(IconComponent, null));
29
+ expect(container.firstChild).toHaveAttribute('data-component-name', dataName);
30
+ },
31
+ };
32
+ }
33
+ //# sourceMappingURL=IconTestUtils.js.map
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CodeWalkthroughLayout = CodeWalkthroughLayout;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const styled_components_1 = __importDefault(require("styled-components"));
9
+ const core_1 = require("../core");
9
10
  function CodeWalkthroughLayout({ className, children, }) {
10
11
  return (react_1.default.createElement(LayoutWrapper, { "data-component-name": "Layout/CodeWalkthroughLayout", className: className },
11
12
  react_1.default.createElement(ContentWrapper, null, children)));
@@ -59,8 +60,10 @@ const ContentWrapper = styled_components_1.default.section `
59
60
 
60
61
  /* Full-width styling for all .code-walkthroughs */
61
62
  .code-walkthrough {
62
- max-width: none;
63
63
  width: 100%;
64
+ max-width: ${core_1.breakpoints.max};
65
+ margin-left: auto;
66
+ margin-right: auto;
64
67
  }
65
68
 
66
69
  &:first-child > h1:first-child {
@@ -43,7 +43,7 @@ function CodeContainer({ highlightedCode, toolbar, }) {
43
43
  }
44
44
  }, 200);
45
45
  }, [activeStep]);
46
- return (react_1.default.createElement(CodeContainerWrapper, { ref: compRef, hideCodeColors: !isHovered, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) },
46
+ return (react_1.default.createElement(CodeContainerWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodeContainer", ref: compRef, hideCodeColors: !isHovered, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) },
47
47
  react_1.default.createElement(CodeBlockContainer_1.CodeBlockContainer, { dangerouslySetInnerHTML: { __html: highlightedCode } }),
48
48
  toolbar));
49
49
  }
@@ -11,7 +11,7 @@ function CodeFilters({ filters, getFilterState, handleFilterSelect, filtersEleme
11
11
  if (filters.length === 0) {
12
12
  return null;
13
13
  }
14
- return (react_1.default.createElement(FilterWrapper, { ref: filtersElementRef }, filters.map(({ label, items, id }) => {
14
+ return (react_1.default.createElement(FilterWrapper, { ref: filtersElementRef, "data-component-name": "Markdoc/CodeWalkthrough/CodeFilters" }, filters.map(({ label, items, id }) => {
15
15
  return (react_1.default.createElement(Filter, { key: id },
16
16
  label && react_1.default.createElement(FilterName, null,
17
17
  label,
@@ -24,8 +24,9 @@ function CodeFilters({ filters, getFilterState, handleFilterSelect, filtersEleme
24
24
  }
25
25
  const Filter = styled_components_1.default.div `
26
26
  display: flex;
27
- align-items: center;
27
+ align-items: flex-start;
28
28
  gap: var(--spacing-xs);
29
+ max-width: 100%;
29
30
  `;
30
31
  const FilterName = styled_components_1.default.div `
31
32
  color: var(--color-text-primary);
@@ -46,13 +47,25 @@ const FilterWrapper = styled_components_1.default.div `
46
47
  top: calc(var(--navbar-height));
47
48
  background-color: var(--bg-color);
48
49
  z-index: 1;
50
+ max-width: var(--md-content-max-width);
49
51
  `;
50
52
  const ButtonsWrapper = styled_components_1.default.div `
51
53
  display: flex;
54
+ min-width: 0;
55
+ flex-wrap: wrap;
52
56
  `;
53
57
  const TagButton = (0, styled_components_1.default)(Tag_1.Tag) `
54
58
  cursor: pointer;
55
59
  padding: 0px var(--spacing-xs);
56
60
  margin-right: var(--spacing-xs);
61
+ max-width: 100%;
62
+ margin-bottom: var(--spacing-xs);
63
+
64
+ ${Tag_1.ContentWrapper} {
65
+ display: inline-block;
66
+ text-overflow: ellipsis;
67
+ white-space: nowrap;
68
+ overflow: hidden;
69
+ }
57
70
  `;
58
71
  //# sourceMappingURL=CodeFilters.js.map
@@ -38,7 +38,7 @@ const CodePanelToolbar_1 = require("../../../markdoc/components/CodeWalkthrough/
38
38
  function CodePanel({ files, downloadAssociatedFiles, preview, }) {
39
39
  const { activeFile, handleTabSwitch, highlightedCode } = (0, hooks_1.useCodePanel)(files);
40
40
  const { handleDownloadCode } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext);
41
- return (react_1.default.createElement(CodePanelWrapper, null,
41
+ return (react_1.default.createElement(CodePanelWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodePanel" },
42
42
  preview ? (react_1.default.createElement(CodePanelPreview_1.CodePanelPreview, null, preview.map((element, idx) => (react_1.default.createElement(react_1.default.Fragment, { key: idx }, element))))) : null,
43
43
  react_1.default.createElement(CodePanelHeader_1.CodePanelHeader, { files: files, activeTabName: (activeFile === null || activeFile === void 0 ? void 0 : activeFile.path) || '', handleTabSwitch: handleTabSwitch, onDownloadCode: () => handleDownloadCode([...files, ...downloadAssociatedFiles]) }),
44
44
  react_1.default.createElement(CodeContainer_1.CodeContainer, { key: (activeFile === null || activeFile === void 0 ? void 0 : activeFile.path) || '', highlightedCode: highlightedCode, toolbar: react_1.default.createElement(CodePanelToolbar_1.CodePanelToolbar, { file: activeFile }) })));
@@ -27,7 +27,6 @@ exports.CodePanelHeader = CodePanelHeader;
27
27
  const react_1 = __importStar(require("react"));
28
28
  const styled_components_1 = __importStar(require("styled-components"));
29
29
  const hooks_1 = require("../../../core/hooks");
30
- const utils_1 = require("../../../core/utils");
31
30
  const OverflowMenuVerticalIcon_1 = require("../../../icons/OverflowMenuVerticalIcon/OverflowMenuVerticalIcon");
32
31
  const Dropdown_1 = require("../../../components/Dropdown/Dropdown");
33
32
  const DropdownMenu_1 = require("../../../components/Dropdown/DropdownMenu");
@@ -35,6 +34,7 @@ const DropdownMenuItem_1 = require("../../../components/Dropdown/DropdownMenuIte
35
34
  const DownloadIcon_1 = require("../../../icons/DownloadIcon/DownloadIcon");
36
35
  const Button_1 = require("../../../components/Button/Button");
37
36
  function CodePanelHeader({ files, handleTabSwitch, activeTabName, onDownloadCode, }) {
37
+ const renderableFiles = (0, hooks_1.useRenderableFiles)(files);
38
38
  const { useTranslate } = (0, hooks_1.useThemeHooks)();
39
39
  const { translate } = useTranslate();
40
40
  const tabRefs = (0, react_1.useRef)([]);
@@ -42,47 +42,49 @@ function CodePanelHeader({ files, handleTabSwitch, activeTabName, onDownloadCode
42
42
  const [hiddenFiles, setHiddenFiles] = (0, react_1.useState)([]);
43
43
  (0, react_1.useEffect)(() => {
44
44
  const activeTab = tabRefs.current.find((tab) => (tab === null || tab === void 0 ? void 0 : tab.dataset.name) === activeTabName);
45
- if (activeTab) {
46
- activeTab.scrollIntoView({ block: 'nearest', inline: 'center' });
45
+ const tabsWrapper = tabsWrapperRef.current;
46
+ if (activeTab && tabsWrapper) {
47
+ const { left: wrapperLeft, right: wrapperRight } = tabsWrapper.getBoundingClientRect();
48
+ const { left: tabLeft, right: tabRight } = activeTab.getBoundingClientRect();
49
+ const tabHidden = tabLeft < wrapperLeft || tabRight > wrapperRight;
50
+ if (tabHidden) {
51
+ activeTab.scrollIntoView({ block: 'nearest', inline: 'nearest' });
52
+ }
47
53
  }
48
- }, [activeTabName]);
49
- (0, react_1.useEffect)(() => {
50
54
  const calculateHiddenFiles = () => {
51
55
  if (!tabsWrapperRef.current)
52
56
  return;
53
57
  const { left: wrapperLeft, right: wrapperRight } = tabsWrapperRef.current.getBoundingClientRect();
54
- const hidden = files.filter((_, i) => {
58
+ const hidden = [];
59
+ for (let i = 0; i < renderableFiles.length; i++) {
55
60
  const tab = tabRefs.current[i];
56
61
  if (!tab)
57
- return false;
62
+ continue;
58
63
  const { left: tabLeft, right: tabRight } = tab.getBoundingClientRect();
59
- return tabLeft < wrapperLeft || tabRight > wrapperRight;
60
- });
64
+ const visible = tabLeft > wrapperLeft && tabRight < wrapperRight;
65
+ if (!visible) {
66
+ hidden.push(renderableFiles[i]);
67
+ }
68
+ }
61
69
  setHiddenFiles(hidden);
62
70
  };
63
71
  calculateHiddenFiles();
64
72
  window.addEventListener('resize', calculateHiddenFiles);
65
73
  return () => window.removeEventListener('resize', calculateHiddenFiles);
66
- }, [files]);
67
- const getFileTypeIcon = (0, react_1.useCallback)((basename) => {
68
- var _a;
69
- const extension = ((_a = basename.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
70
- return (0, utils_1.getFileIconByExt)(extension);
71
- }, []);
74
+ }, [activeTabName, files, renderableFiles]);
72
75
  return (react_1.default.createElement(CodePanelHeaderWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodePanelHeader" },
73
76
  react_1.default.createElement(TabsWrapper, { ref: tabsWrapperRef },
74
- react_1.default.createElement(Tabs, null, files.map(({ path, basename }, i) => {
75
- const FileIcon = getFileTypeIcon(basename);
77
+ react_1.default.createElement(Tabs, null, renderableFiles.map(({ path, basename, FileIcon, parentFolder, isNameDuplicate, inRootDir }, i) => {
76
78
  return (react_1.default.createElement(Tab, { ref: (el) => (tabRefs.current[i] = el), "data-name": path, active: path === activeTabName, key: i, onClick: () => handleTabSwitch(path) },
77
79
  react_1.default.createElement(FileIcon, null),
78
- basename));
80
+ basename,
81
+ isNameDuplicate && !inRootDir ? react_1.default.createElement(Dirname, null, parentFolder) : null));
79
82
  })),
80
83
  react_1.default.createElement(Gradient, null)),
81
84
  react_1.default.createElement(ActionBar, null,
82
85
  hiddenFiles.length ? (react_1.default.createElement(Dropdown_1.Dropdown, { trigger: react_1.default.createElement(StyledOverflowMenuVerticalIcon, { size: "14px" }), alignment: "end" },
83
- react_1.default.createElement(StyledDropdownMenu, null, hiddenFiles.map(({ path, basename }, i) => {
84
- const FileIcon = getFileTypeIcon(basename);
85
- return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { active: path === activeTabName, key: i, onAction: () => handleTabSwitch(path), prefix: react_1.default.createElement(FileIcon, null), content: basename }));
86
+ react_1.default.createElement(StyledDropdownMenu, null, hiddenFiles.map(({ path, basename, FileIcon, isNameDuplicate, inRootDir, parentFolder }, i) => {
87
+ return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { active: path === activeTabName, key: i, onAction: () => handleTabSwitch(path), prefix: react_1.default.createElement(FileIcon, null), content: isNameDuplicate && !inRootDir ? `${parentFolder}/${basename}` : basename }));
86
88
  })))) : null,
87
89
  react_1.default.createElement(Button_1.Button, { variant: "text", icon: react_1.default.createElement(DownloadIcon_1.DownloadIcon, null), onClick: onDownloadCode, size: "small" }, translate('codeWalkthrough.download', 'Download')))));
88
90
  }
@@ -108,13 +110,17 @@ const Gradient = styled_components_1.default.div `
108
110
  `;
109
111
  const Tabs = styled_components_1.default.div `
110
112
  display: flex;
111
- overflow-x: auto;
113
+ overflow-x: hidden;
112
114
  padding-right: var(--spacing-base);
113
115
 
114
116
  &::-webkit-scrollbar {
115
117
  display: none;
116
118
  }
117
119
  `;
120
+ const Dirname = styled_components_1.default.span `
121
+ font-size: var(--font-size-sm);
122
+ color: var(--text-color-description);
123
+ `;
118
124
  const ActionBar = styled_components_1.default.div `
119
125
  display: flex;
120
126
  `;
@@ -129,7 +135,7 @@ const Tab = styled_components_1.default.button `
129
135
  gap: var(--spacing-xs);
130
136
  color: var(--text-color-secondary);
131
137
  white-space: nowrap;
132
-
138
+ scroll-margin-right: var(--spacing-base);
133
139
  ${({ active }) => active
134
140
  ? (0, styled_components_1.css) `
135
141
  color: var(--text-color-primary);
@@ -36,7 +36,7 @@ function CodePanelPreview({ children }) {
36
36
  const [isOpen, setIsOpen] = (0, react_1.useState)(false);
37
37
  const { useTranslate } = (0, hooks_1.useThemeHooks)();
38
38
  const { translate } = useTranslate();
39
- return (react_1.default.createElement(CodePanelPreviewWrapper, null,
39
+ return (react_1.default.createElement(CodePanelPreviewWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodePanelPreview" },
40
40
  react_1.default.createElement(PreviewDropdown, { onClick: () => setIsOpen(!isOpen) },
41
41
  translate('codeWalkthrough.preview', 'Preview'),
42
42
  isOpen ? react_1.default.createElement(ChevronUpIcon_1.ChevronUpIcon, null) : react_1.default.createElement(ChevronDownIcon_1.ChevronDownIcon, null)),
@@ -34,7 +34,7 @@ const CopyButton_1 = require("../../../components/Buttons/CopyButton");
34
34
  function CodePanelToolbar({ file }) {
35
35
  const { getFileText } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext);
36
36
  const fileContent = getFileText(file);
37
- return (react_1.default.createElement(CodeToolbarWrapper, null,
37
+ return (react_1.default.createElement(CodeToolbarWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodePanelToolbar" },
38
38
  react_1.default.createElement(CopyButton_1.CopyButton, { data: fileContent, type: "compound", variant: "secondary", size: "medium" })));
39
39
  }
40
40
  const CodeToolbarWrapper = styled_components_1.default.div `
@@ -41,7 +41,7 @@ function CodeStep({ id, heading, stepKey, when, unless, children, }) {
41
41
  if (lockObserver) {
42
42
  lockObserver.current = true;
43
43
  if (compRef.current) {
44
- compRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
44
+ compRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
45
45
  }
46
46
  setActiveStep(id);
47
47
  setTimeout(() => {
@@ -71,7 +71,7 @@ function CodeStep({ id, heading, stepKey, when, unless, children, }) {
71
71
  }
72
72
  const filtersElementHeight = ((_a = filtersElementRef === null || filtersElementRef === void 0 ? void 0 : filtersElementRef.current) === null || _a === void 0 ? void 0 : _a.clientHeight) || 0;
73
73
  const navbarHeight = ((_b = document.querySelector('nav')) === null || _b === void 0 ? void 0 : _b.clientHeight) || 0;
74
- setScrollMarginTop(filtersElementHeight + navbarHeight);
74
+ setScrollMarginTop(filtersElementHeight + navbarHeight + 10);
75
75
  return () => {
76
76
  if (currentCompRef) {
77
77
  unregister(currentCompRef);
@@ -79,9 +79,12 @@ function CodeStep({ id, heading, stepKey, when, unless, children, }) {
79
79
  };
80
80
  }, [activeStep, register, unregister, filtersElementRef]);
81
81
  if (!areConditionsMet({ when, unless })) {
82
+ if (isActive) {
83
+ setActiveStep(null);
84
+ }
82
85
  return null;
83
86
  }
84
- return (react_1.default.createElement(exports.StepWrapper, { ref: compRef, isActive: isActive, scrollMarginTop: scrollMarginTop, "data-step-key": stepKey, "data-step-active": isActive, onClick: handleActivateStep, onFocus: handleActivateStep, tabIndex: 0 },
87
+ return (react_1.default.createElement(exports.StepWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodeStep", ref: compRef, isActive: isActive, scrollMarginTop: scrollMarginTop, "data-step-key": stepKey, "data-step-active": isActive, onClick: handleActivateStep, onFocus: handleActivateStep, tabIndex: 0 },
85
88
  react_1.default.createElement(StepContent, { isActive: isActive },
86
89
  heading ? react_1.default.createElement(StepHeading, null, heading) : null,
87
90
  children)));
@@ -41,7 +41,7 @@ function CodeToggle(props) {
41
41
  return null;
42
42
  }
43
43
  const checked = toggleState.value;
44
- return (react_1.default.createElement(exports.ToggleWrapper, null,
44
+ return (react_1.default.createElement(exports.ToggleWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodeToggle" },
45
45
  react_1.default.createElement(ToggleContentWrapper, null,
46
46
  react_1.default.createElement(exports.ToggleSubtitle, null,
47
47
  react_1.default.createElement(Switch_1.Switch, { value: checked, onChange: (newValue) => changeToggleState(id, newValue) }),
@@ -55,7 +55,7 @@ function CodeWalkthrough(_a) {
55
55
  const { filtersElementRef } = stepsState;
56
56
  return (react_1.default.createElement(contexts_1.CodeWalkthroughStepsContext.Provider, { value: stepsState },
57
57
  react_1.default.createElement(contexts_1.CodeWalkthroughControlsStateContext.Provider, { value: controlsState },
58
- react_1.default.createElement(CodeWalkthroughWrapper, { className: "code-walkthrough" },
58
+ react_1.default.createElement(CodeWalkthroughWrapper, { className: "code-walkthrough", "data-component-name": "Markdoc/CodeWalkthrough/CodeWalkthrough" },
59
59
  react_1.default.createElement(DocsPanel, null,
60
60
  react_1.default.createElement(CodeFilters_1.CodeFilters, { filters: activeFilters, getFilterState: getFilterState, handleFilterSelect: changeFilterState, filtersElementRef: filtersElementRef }),
61
61
  react_1.default.createElement(ContentWrapper, null, children)),
@@ -49,14 +49,15 @@ function Input(props) {
49
49
  setValue(inputValue);
50
50
  debouncedSave(id, inputValue);
51
51
  };
52
- return (react_1.default.createElement(InputWrapper, null,
52
+ return (react_1.default.createElement(InputWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/Input" },
53
53
  label && react_1.default.createElement(Label, null, label),
54
54
  react_1.default.createElement(StyledInput, { id: id, value: value, onChange: handleChange, "aria-label": label, placeholder: placeholder })));
55
55
  }
56
56
  const InputWrapper = styled_components_1.default.div `
57
57
  display: flex;
58
58
  flex-direction: column;
59
- margin: var(--md-paragraph-margin);
59
+ margin-top: var(--spacing-base);
60
+ margin-bottom: var(--spacing-base);
60
61
  `;
61
62
  const Label = styled_components_1.default.p `
62
63
  color: var(--text-color-secondary);
@@ -64,6 +65,7 @@ const Label = styled_components_1.default.p `
64
65
  line-height: var(--line-height-base);
65
66
  font-family: var(--font-family-base);
66
67
  font-weight: var(--font-weight-medium);
68
+ margin-bottom: var(--spacing-xxs) !important;
67
69
  `;
68
70
  const StyledInput = styled_components_1.default.input `
69
71
  border: 1px solid var(--border-color-primary);
@@ -41,6 +41,11 @@ exports.codeWalkthrough = {
41
41
  render: false,
42
42
  required: false,
43
43
  },
44
+ __idx: {
45
+ type: Number,
46
+ render: true,
47
+ required: false,
48
+ },
44
49
  },
45
50
  slots: {
46
51
  preview: { required: false, render: true },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.47.1",
3
+ "version": "0.48.1",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -46,7 +46,7 @@
46
46
  "@types/jest-when": "3.5.5",
47
47
  "@types/lodash.debounce": "4.0.9",
48
48
  "@types/lodash.throttle": "4.1.9",
49
- "@types/node": "18.19.3",
49
+ "@types/node": "22.10.5",
50
50
  "@types/react": "18.3.9",
51
51
  "@types/react-dom": "18.3.5",
52
52
  "@types/styled-components": "5.1.34",
@@ -86,7 +86,7 @@
86
86
  "timeago.js": "4.0.2",
87
87
  "i18next": "22.4.15",
88
88
  "nprogress": "0.2.0",
89
- "@redocly/config": "0.19.4"
89
+ "@redocly/config": "0.20.1"
90
90
  },
91
91
  "scripts": {
92
92
  "watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
- import styled from 'styled-components';
3
+ import styled, { css } from 'styled-components';
4
4
 
5
- import type { AnonymousUserEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
5
+ import type { OptionalEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
7
7
 
8
8
  import { Reasons } from '@redocly/theme/components/Feedback/Reasons';
@@ -41,7 +41,7 @@ export type MoodProps = {
41
41
  neutral?: ReasonsSettingsSchema;
42
42
  dissatisfied?: ReasonsSettingsSchema;
43
43
  };
44
- anonymousUserEmail?: AnonymousUserEmailSettings;
44
+ optionalEmail?: OptionalEmailSettings;
45
45
  };
46
46
  className?: string;
47
47
  };
@@ -52,7 +52,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
52
52
  submitText,
53
53
  comment: commentSettings,
54
54
  reasons: reasonsSettings,
55
- anonymousUserEmail: anonymousUserEmailSettings,
55
+ optionalEmail: optionalEmailSettings,
56
56
  } = settings || {};
57
57
  const [score, setScore] = React.useState('');
58
58
  const [isSubmitted, setIsSubmitted] = React.useState(false);
@@ -131,8 +131,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
131
131
  const displayReasons = checkIfShouldDisplayReasons(score);
132
132
  const displayComment = !!(score && !commentSettings?.hide);
133
133
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
134
- const displayFeedbackEmail =
135
- !!score && anonymousUserEmailSettings?.enabled && !userData.isAuthenticated;
134
+ const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
136
135
 
137
136
  const onSubmitMoodForm = () => {
138
137
  onSubmit({
@@ -162,7 +161,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
162
161
  return (
163
162
  <MoodWrapper data-component-name="Feedback/Mood">
164
163
  <StyledFormMandatoryFields>
165
- <Label data-translation-key="feedback.settings.submitText">
164
+ <Label standAlone={true} data-translation-key="feedback.settings.submitText">
166
165
  {submitText ||
167
166
  translate(
168
167
  'feedback.settings.submitText',
@@ -179,7 +178,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
179
178
  <MoodWrapper data-component-name="Feedback/Mood" className={className}>
180
179
  <StyledForm onSubmit={onSubmitMoodForm}>
181
180
  <StyledFormMandatoryFields>
182
- <Label data-translation-key="feedback.settings.label">
181
+ <Label standAlone={true} data-translation-key="feedback.settings.label">
183
182
  {label || translate('feedback.settings.label', 'Was this helpful?')}
184
183
  </Label>
185
184
  <StyledMandatoryFieldContainer>
@@ -241,18 +240,18 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
241
240
 
242
241
  {displayFeedbackEmail && (
243
242
  <StyledFormOptionalFields>
244
- <Label data-translation-key="feedback.settings.anonymousUserEmail.label">
245
- {anonymousUserEmailSettings?.label ||
243
+ <Label data-translation-key="feedback.settings.optionalEmail.label">
244
+ {optionalEmailSettings?.label ||
246
245
  translate(
247
- 'feedback.settings.anonymousUserEmail.label',
246
+ 'feedback.settings.optionalEmail.label',
248
247
  'Your email (optional, for follow-up)',
249
248
  )}
250
249
  </Label>
251
250
  <EmailInput
252
251
  onChange={onEmailChange}
253
252
  placeholder={
254
- anonymousUserEmailSettings?.placeholder ||
255
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com')
253
+ optionalEmailSettings?.placeholder ||
254
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com')
256
255
  }
257
256
  type="email"
258
257
  required={!!email}
@@ -295,12 +294,21 @@ const MoodWrapper = styled.div`
295
294
  align-items: center;
296
295
  `;
297
296
 
298
- const Label = styled.h4`
297
+ const Label = styled.h4<{ standAlone?: boolean }>`
299
298
  font-family: var(--feedback-font-family);
300
299
  font-weight: var(--font-weight-regular);
301
- font-size: var(--feedback-header-font-size);
302
- line-height: var(--feedback-header-line-height);
303
- color: var(--feedback-header-text-color);
300
+ font-size: var(--feedback-font-size);
301
+ line-height: var(--feedback-line-height);
302
+ color: var(--feedback-text-color);
303
+
304
+ ${({ standAlone = false }) =>
305
+ standAlone &&
306
+ css`
307
+ font-size: var(--feedback-header-font-size);
308
+ line-height: var(--feedback-header-line-height);
309
+ color: var(--feedback-header-text-color);
310
+ `}
311
+
304
312
  margin: 0;
305
313
  `;
306
314
 
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
3
  import styled from 'styled-components';
4
4
 
5
- import type { AnonymousUserEmailSettings } from '@redocly/config';
5
+ import type { OptionalEmailSettings } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
7
7
 
8
8
  import { Reasons } from '@redocly/theme/components/Feedback/Reasons';
@@ -35,7 +35,7 @@ export type RatingProps = {
35
35
  component?: string;
36
36
  items: string[];
37
37
  };
38
- anonymousUserEmail?: AnonymousUserEmailSettings;
38
+ optionalEmail?: OptionalEmailSettings;
39
39
  };
40
40
  className?: string;
41
41
  };
@@ -46,7 +46,7 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
46
46
  submitText,
47
47
  comment: commentSettings,
48
48
  reasons: reasonsSettings,
49
- anonymousUserEmail: anonymousUserEmailSettings,
49
+ optionalEmail: optionalEmailSettings,
50
50
  } = settings || {};
51
51
  const [isSubmitted, setIsSubmitted] = React.useState(false);
52
52
  const [score, setScore] = React.useState(0);
@@ -83,8 +83,7 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
83
83
  const displayReasons = !!(score && reasonsSettings && !reasonsSettings.hide);
84
84
  const displayComment = !!(score && !commentSettings?.hide);
85
85
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
86
- const displayFeedbackEmail =
87
- !!score && anonymousUserEmailSettings?.enabled && !userData.isAuthenticated;
86
+ const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
88
87
 
89
88
  useEffect(() => {
90
89
  if (score && !displayComment && !displayReasons && !displayFeedbackEmail) {
@@ -154,18 +153,18 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
154
153
 
155
154
  {displayFeedbackEmail && (
156
155
  <StyledFormOptionalFields>
157
- <Label data-translation-key="feedback.settings.anonymousUserEmail.label">
158
- {anonymousUserEmailSettings?.label ||
156
+ <Label data-translation-key="feedback.settings.optionalEmail.label">
157
+ {optionalEmailSettings?.label ||
159
158
  translate(
160
- 'feedback.settings.anonymousUserEmail.label',
159
+ 'feedback.settings.optionalEmail.label',
161
160
  'Your email (optional, for follow-up)',
162
161
  )}
163
162
  </Label>
164
163
  <EmailInput
165
164
  onChange={onEmailChange}
166
165
  placeholder={
167
- anonymousUserEmailSettings?.placeholder ||
168
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com')
166
+ optionalEmailSettings?.placeholder ||
167
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com')
169
168
  }
170
169
  type="email"
171
170
  required={!!email}
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
3
  import styled from 'styled-components';
4
4
 
5
- import type { AnonymousUserEmailSettings } from '@redocly/config';
5
+ import type { OptionalEmailSettings } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
7
7
 
8
8
  import { breakpoints } from '@redocly/theme/core/utils';
@@ -37,7 +37,7 @@ export type ScaleProps = {
37
37
  component?: string;
38
38
  items: string[];
39
39
  };
40
- anonymousUserEmail?: AnonymousUserEmailSettings;
40
+ optionalEmail?: OptionalEmailSettings;
41
41
  };
42
42
  className?: string;
43
43
  };
@@ -50,7 +50,7 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
50
50
  rightScaleLabel,
51
51
  comment: commentSettings,
52
52
  reasons: reasonsSettings,
53
- anonymousUserEmail: anonymousUserEmailSettings,
53
+ optionalEmail: optionalEmailSettings,
54
54
  } = settings || {};
55
55
  const [score, setScore] = React.useState(0);
56
56
  const [isSubmitted, setIsSubmitted] = React.useState(false);
@@ -85,8 +85,7 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
85
85
  const displayReasons = !!score && reasonsSettings && !reasonsSettings.hide;
86
86
  const displayComment = !!(score && !commentSettings?.hide);
87
87
  const displaySubmitBnt = !!score && (displayReasons || displayComment);
88
- const displayFeedbackEmail =
89
- !!score && anonymousUserEmailSettings?.enabled && !userData.isAuthenticated;
88
+ const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
90
89
 
91
90
  const handleCancel = () => {
92
91
  setScore(0);
@@ -179,18 +178,18 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
179
178
 
180
179
  {displayFeedbackEmail && (
181
180
  <StyledFormOptionalFields>
182
- <Label data-translation-key="feedback.settings.anonymousUserEmail.label">
183
- {anonymousUserEmailSettings?.label ||
181
+ <Label data-translation-key="feedback.settings.optionalEmail.label">
182
+ {optionalEmailSettings?.label ||
184
183
  translate(
185
- 'feedback.settings.anonymousUserEmail.label',
184
+ 'feedback.settings.optionalEmail.label',
186
185
  'Your email (optional, for follow-up)',
187
186
  )}
188
187
  </Label>
189
188
  <EmailInput
190
189
  onChange={onEmailChange}
191
190
  placeholder={
192
- anonymousUserEmailSettings?.placeholder ||
193
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com')
191
+ optionalEmailSettings?.placeholder ||
192
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com')
194
193
  }
195
194
  type="email"
196
195
  required={!!email}